Add headers for OpenSolaris extensions that glibc implements
[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 <portP.h>
22 #include <port.h>
23
24 /* SYS_port returns a 64-bit int but the port_* calls return a 32-bit int, so
25    we can't implement these directly in syscalls.list.  Whenever the 2nd
26    argument is not a port we need to specify PORT_SYS_NOPORT.
27
28    port_getn and port_sendn are special in that they may return after only
29    some of the ports have been acted on before the timeout occured. In this
30    case, the first 32-bits of the the return specify the number of acted on
31    ports, and the second 32-bits specify the error that occured (currently
32    this is always ETIME).  */
33
34 DECLARE_INLINE_SYSCALL (int64_t, port, int, ...);
35
36
37 int port_create (void)
38 {
39   /* The 2nd argument is the version of port_create, currently 0.  */
40   rval_t ret;
41   ret.rval64 = INLINE_SYSCALL (port, 2,
42     SYS_SUB_port_create | PORT_SYS_NOPORT, 0);
43   return ret.rval1;
44 }
45
46 int port_associate (int port, int source, uintptr_t object,
47       int events, void *user)
48 {
49   rval_t ret;
50   ret.rval64 = INLINE_SYSCALL (port, 6, SYS_SUB_port_associate, port, source,
51     object, events, user);
52   return ret.rval1;
53 }
54
55 int port_dissociate (int port, int source, uintptr_t object)
56 {
57   rval_t ret;
58   ret.rval64 = INLINE_SYSCALL (port, 4, SYS_SUB_port_dissociate, port,
59       source, object);
60   return ret.rval1;
61 }
62
63 int port_send (int port, int events, void *user)
64 {
65   rval_t ret;
66   ret.rval64 = INLINE_SYSCALL (port, 4, SYS_SUB_port_send, port, events, user);
67   return ret.rval1;
68 }
69
70 int port_sendn (int ports[], int errors[], unsigned int nent,
71       int events, void *user)
72 {
73   /* Note that we cannot have more than PORT_MAX_LIST ports in a single
74      syscall so we may need to split ports across multiple syscalls.  */
75
76   rval_t ret;
77   int nevents = 0;
78   for (unsigned int i = 0; i < nent; i += PORT_MAX_LIST)
79     {
80       int errval = __systemcall (&ret.rvals, SYS_port, SYS_SUB_port_sendn |
81         PORT_SYS_NOPORT, &ports[i], &errors[i], MIN (nent - i, PORT_MAX_LIST),
82         events, user);
83       if (errval == 0 || errval == ETIME)
84           nevents += ret.rval1;
85       if (errval != 0)
86         {
87           __set_errno (errval);
88           break;
89         }
90     }
91
92   return nevents;
93 }
94
95 int port_get (int port, port_event_t *pe, struct timespec *to)
96 {
97   time_t sec = to ? to->tv_sec : 0;
98   long nsec = to ? to->tv_nsec : 0;
99   rval_t ret;
100   ret.rval64 = INLINE_SYSCALL (port, 6, SYS_SUB_port_get, port, pe, sec, nsec, to);
101   return ret.rval1;
102 }
103
104 int port_getn (int port, port_event_t list[], unsigned int max,
105       unsigned int *nget, struct timespec *timeout)
106 {
107   rval_t ret;
108   int errval = __systemcall (&ret.rvals, SYS_port, SYS_SUB_port_getn, port, list,
109     max, *nget, timeout);
110   if (errval == 0 || errval == ETIME)
111     *nget = ret.rval1;
112
113   if (errval != 0)
114     {
115       __set_errno (errval);
116       return -1;
117     }
118   return 0;
119 }
120
121 int port_alert (int port, int flags, int events, void *user)
122 {
123   rval_t ret;
124   ret.rval64 = INLINE_SYSCALL (port, 5, SYS_SUB_port_alert, port, flags,
125     events, user);
126   return ret.rval1;
127 }