Lots of changes
[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 <sys/port_impl.h>
24 #include <port.h>
25
26 /* SYS_port returns a 64-bit int but the port_* calls return a 32-bit int, so
27    we can't implement these directly in syscalls.list.  Whenever the 2nd
28    argument is not a port we need to specify PORT_SYS_NOPORT.
29
30    port_getn and port_sendn are special in that they may return after only
31    some of the ports have been acted on before the timeout occured. In this
32    case, the first 32-bits of the the return specify the number of acted on
33    ports, and the second 32-bits specify the error that occured (currently
34    this is always ETIME).  */
35
36 DECLARE_INLINE_SYSCALL (int64_t, port, int, ...);
37
38
39 int port_create (void)
40 {
41   /* The 2nd argument is the version on PORT_CREATE, currently 0.  */
42   rval_t ret;
43   ret.rval64 = INLINE_SYSCALL (port, 2, 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, PORT_ASSOCIATE, port, source, object,
52       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, PORT_DISSOCIATE, port, 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, 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 (SYS_port, &ret, PORT_SENDN | PORT_SYS_NOPORT,
81         &ports[i], &errors[i], MIN (nent - i, PORT_MAX_LIST), events, user);
82       if (errval == 0 || errval == ETIME)
83           nevents += ret.rval1;
84       if (errval != 0)
85         {
86           __set_errno (errval);
87           break;
88         }
89     }
90
91   return nevents;
92 }
93
94 int port_get (int port, port_event_t *pe, struct timespec *to)
95 {
96   time_t sec = to ? to->tv_sec : 0;
97   long nsec = to ? to->tv_nsec : 0;
98   rval_t ret;
99   ret.rval64 = INLINE_SYSCALL (port, 6, PORT_GET, port, pe, sec, nsec, to);
100   return ret.rval1;
101 }
102
103 int port_getn (int port, port_event_t list[], unsigned int max,
104       unsigned int *nget, struct timespec *timeout)
105 {
106   rval_t ret;
107   int errval = __systemcall (SYS_port, &ret, PORT_GETN, port, list, max,
108     *nget, timeout);
109   if (errval == 0 || errval == ETIME)
110     *nget = ret.rval1;
111
112   if (errval != 0)
113     {
114       __set_errno (errval);
115       return -1;
116     }
117   return 0;
118 }
119
120 int port_alert (int port, int flags, int events, void *user)
121 {
122   rval_t ret;
123   ret.rval64 = INLINE_SYSCALL (port, 5, PORT_ALERT, port, flags, events, user);
124   return ret.rval1;
125 }