9a4f3e02af01dea09c2926255ddbd24e3a98e6e9
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / port.c
1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <inline-syscall.h>
21 #include <sys/types.h>
22 #include <sys/param.h>
23 #include <portP.h>
24
25 /* SYS_port returns a 64-bit int but the port_* calls return a 32-bit int, so
26    we can't implement these directly in syscalls.list.  Whenever the 2nd
27    argument is not a port we need to specify PORT_SYS_NOPORT.
28
29    port_getn and port_sendn are special in that they may return after only
30    some of the ports have been acted on before the timeout occured. In this
31    case, the first 32-bits of the the return specify the number of acted on
32    ports, and the second 32-bits specify the error that occured (currently
33    this is always ETIME).  */
34
35 DECLARE_INLINE_SYSCALL (int64_t, port, int, ...);
36
37
38 int port_create (void)
39 {
40   /* The 2nd argument is the version of port_create, currently 0.  */
41   rval_t ret;
42   ret.rval64 = INLINE_SYSCALL (port, 2,
43     SYS_SUB_port_create | PORT_SYS_NOPORT, 0);
44   return ret.rval1;
45 }
46
47 int port_associate (int port, int source, uintptr_t object,
48       int events, void *user)
49 {
50   rval_t ret;
51   ret.rval64 = INLINE_SYSCALL (port, 6, SYS_SUB_port_associate, port, source,
52     object, events, user);
53   return ret.rval1;
54 }
55
56 int port_dissociate (int port, int source, uintptr_t object)
57 {
58   rval_t ret;
59   ret.rval64 = INLINE_SYSCALL (port, 4, SYS_SUB_port_dissociate, port,
60       source, object);
61   return ret.rval1;
62 }
63
64 int port_send (int port, int events, void *user)
65 {
66   rval_t ret;
67   ret.rval64 = INLINE_SYSCALL (port, 4, SYS_SUB_port_send, port, events, user);
68   return ret.rval1;
69 }
70
71 int port_sendn (int ports[], int errors[], unsigned int nent,
72       int events, void *user)
73 {
74   /* Note that we cannot have more than PORT_MAX_LIST ports in a single
75      syscall so we may need to split ports across multiple syscalls.  */
76
77   rval_t ret;
78   int nevents = 0;
79   for (unsigned int i = 0; i < nent; i += PORT_MAX_LIST)
80     {
81       int errval = __systemcall (&ret.rvals, SYS_port, SYS_SUB_port_sendn |
82         PORT_SYS_NOPORT, &ports[i], &errors[i], MIN (nent - i, PORT_MAX_LIST),
83         events, user);
84       if (errval == 0 || errval == ETIME)
85           nevents += ret.rval1;
86       if (errval != 0)
87         {
88           __set_errno (errval);
89           break;
90         }
91     }
92
93   return nevents;
94 }
95
96 int port_get (int port, port_event_t *pe, struct timespec *to)
97 {
98   time_t sec = to ? to->tv_sec : 0;
99   long nsec = to ? to->tv_nsec : 0;
100   rval_t ret;
101   ret.rval64 = INLINE_SYSCALL (port, 6, SYS_SUB_port_get, port, pe, sec, nsec, to);
102   return ret.rval1;
103 }
104
105 int port_getn (int port, port_event_t list[], unsigned int max,
106       unsigned int *nget, struct timespec *timeout)
107 {
108   rval_t ret;
109   int errval = __systemcall (&ret.rvals, SYS_port, SYS_SUB_port_getn, port, list,
110     max, *nget, timeout);
111   if (errval == 0 || errval == ETIME)
112     *nget = ret.rval1;
113
114   if (errval != 0)
115     {
116       __set_errno (errval);
117       return -1;
118     }
119   return 0;
120 }
121
122 int port_alert (int port, int flags, int events, void *user)
123 {
124   rval_t ret;
125   ret.rval64 = INLINE_SYSCALL (port, 5, SYS_SUB_port_alert, port, flags,
126     events, user);
127   return ret.rval1;
128 }