]>
sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/posix_ipc.cc
1 /* posix_ipc.cc: POSIX IPC API for Cygwin.
3 Copyright 2007 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
21 #include <sys/param.h>
25 #include <semaphore.h>
27 /* The prefix_len is the length of the path prefix ncluding trailing "/"
28 (or "/sem." for semaphores) as well as the trailing NUL. */
32 const size_t prefix_len
;
33 const char *description
;
35 { "/dev/shm", 10, "POSIX shared memory object" },
36 { "/dev/mqueue", 13, "POSIX message queue" },
37 { "/dev/shm", 14, "POSIX semaphore" }
48 check_path (char *res_name
, ipc_type_t type
, const char *name
, size_t len
)
50 /* Note that we require the existance of the apprpriate /dev subdirectories
51 for POSIX IPC object support, similar to Linux (which supports the
52 directories, but doesn't require to mount them). We don't create
53 these directory here, that's the task of the installer. But we check
54 for existance and give ample warning. */
55 path_conv
path (ipc_names
[type
].prefix
, PC_SYM_NOFOLLOW
);
56 if (path
.error
|| !path
.exists () || !path
.isdir ())
59 "Warning: '%s' does not exists or is not a directory.\n\n"
60 "%ss require the existance of this directory.\n"
61 "Create the directory '%s' and set the permissions to 01777.\n"
62 "For instance on the command line: mkdir -m 01777 %s\n",
63 ipc_names
[type
].prefix
, ipc_names
[type
].description
,
64 ipc_names
[type
].prefix
, ipc_names
[type
].prefix
);
68 /* Name must start with a single slash. */
69 if (!name
|| name
[0] != '/' || name
[1] == '/' || !name
[1])
71 debug_printf ("Invalid %s name '%s'", ipc_names
[type
].description
, name
);
75 if (len
> PATH_MAX
- ipc_names
[type
].prefix_len
)
77 debug_printf ("%s name '%s' too long", ipc_names
[type
].description
, name
);
78 set_errno (ENAMETOOLONG
);
81 __small_sprintf (res_name
, "%s/%s%s", ipc_names
[type
].prefix
,
82 type
== semaphore
? "sem." : "",
88 ipc_mutex_init (HANDLE
*pmtx
, const char *name
)
91 SECURITY_ATTRIBUTES sa
= sec_none
;
93 __small_sprintf (buf
, "mqueue/mtx_%s", name
);
94 sa
.lpSecurityDescriptor
= everyone_sd (CYG_MUTANT_ACCESS
);
95 *pmtx
= CreateMutex (&sa
, FALSE
, buf
);
97 debug_printf ("CreateMutex: %E");
98 return *pmtx
? 0 : geterrno_from_win_error ();
102 ipc_mutex_lock (HANDLE mtx
)
104 HANDLE h
[2] = { mtx
, signal_arrived
};
106 switch (WaitForMultipleObjects (2, h
, FALSE
, INFINITE
))
109 case WAIT_ABANDONED_0
:
111 case WAIT_OBJECT_0
+ 1:
117 return geterrno_from_win_error ();
121 ipc_mutex_unlock (HANDLE mtx
)
123 return ReleaseMutex (mtx
) ? 0 : geterrno_from_win_error ();
127 ipc_mutex_close (HANDLE mtx
)
129 return CloseHandle (mtx
) ? 0 : geterrno_from_win_error ();
133 ipc_cond_init (HANDLE
*pevt
, const char *name
)
136 SECURITY_ATTRIBUTES sa
= sec_none
;
138 __small_sprintf (buf
, "mqueue/evt_%s", name
);
139 sa
.lpSecurityDescriptor
= everyone_sd (CYG_EVENT_ACCESS
);
140 *pevt
= CreateEvent (&sa
, TRUE
, FALSE
, buf
);
142 debug_printf ("CreateEvent: %E");
143 return *pevt
? 0 : geterrno_from_win_error ();
147 ipc_cond_timedwait (HANDLE evt
, HANDLE mtx
, const struct timespec
*abstime
)
151 HANDLE h
[2] = { mtx
, evt
};
155 else if (abstime
->tv_sec
< 0
156 || abstime
->tv_nsec
< 0
157 || abstime
->tv_nsec
> 999999999)
161 gettimeofday (&tv
, NULL
);
162 /* Check for immediate timeout. */
163 if (tv
.tv_sec
> abstime
->tv_sec
164 || (tv
.tv_sec
== abstime
->tv_sec
165 && tv
.tv_usec
> abstime
->tv_nsec
/ 1000))
167 timeout
= (abstime
->tv_sec
- tv
.tv_sec
) * 1000;
168 timeout
+= (abstime
->tv_nsec
/ 1000 - tv
.tv_usec
) / 1000;
170 if (ipc_mutex_unlock (mtx
))
172 switch (WaitForMultipleObjects (2, h
, TRUE
, timeout
))
175 case WAIT_ABANDONED_0
:
179 ipc_mutex_lock (mtx
);
184 return geterrno_from_win_error ();
188 ipc_cond_signal (HANDLE evt
)
190 return SetEvent (evt
) ? 0 : geterrno_from_win_error ();
194 ipc_cond_close (HANDLE evt
)
196 return CloseHandle (evt
) ? 0 : geterrno_from_win_error ();
204 ipc_flock () { memset (&fl
, 0, sizeof fl
); }
206 int lock (int fd
, size_t size
)
209 fl
.l_whence
= SEEK_SET
;
212 return fcntl64 (fd
, F_SETLKW
, &fl
);
219 return fcntl64 (fd
, F_SETLKW
, &fl
);
223 /* POSIX shared memory object implementation. */
226 shm_open (const char *name
, int oflag
, mode_t mode
)
228 size_t len
= strlen (name
);
229 char shmname
[ipc_names
[shmem
].prefix_len
+ len
];
231 if (!check_path (shmname
, shmem
, name
, len
))
234 /* Check for valid flags. */
235 if (((oflag
& O_ACCMODE
) != O_RDONLY
&& (oflag
& O_ACCMODE
) != O_RDWR
)
236 || (oflag
& ~(O_ACCMODE
| O_CREAT
| O_EXCL
| O_TRUNC
)))
238 debug_printf ("Invalid oflag 0%o", oflag
);
243 return open (shmname
, oflag
, mode
& 0777);
247 shm_unlink (const char *name
)
249 size_t len
= strlen (name
);
250 char shmname
[ipc_names
[shmem
].prefix_len
+ len
];
252 if (!check_path (shmname
, shmem
, name
, len
))
255 return unlink (shmname
);
258 /* The POSIX message queue implementation is based on W. Richard STEVENS
259 implementation, just tweaked for Cygwin. The main change is
260 the usage of Windows mutexes and events instead of using the pthread
261 synchronization objects. The pathname is massaged so that the
262 files are created under /dev/mqueue. mq_timedsend and mq_timedreceive
263 are implemented additionally. */
267 struct mq_attr mqh_attr
; /* the queue's attributes */
268 long mqh_head
; /* index of first message */
269 long mqh_free
; /* index of first free message */
270 long mqh_nwait
; /* #threads blocked in mq_receive() */
271 pid_t mqh_pid
; /* nonzero PID if mqh_event set */
272 char mqh_uname
[36]; /* unique name used to identify synchronization
273 objects connected to this queue */
274 struct sigevent mqh_event
; /* for mq_notify() */
279 long msg_next
; /* index of next on linked list */
280 ssize_t msg_len
; /* actual length */
281 unsigned int msg_prio
; /* priority */
286 struct mq_hdr
*mqi_hdr
; /* start of mmap'ed region */
287 unsigned long mqi_magic
; /* magic number if open */
288 int mqi_flags
; /* flags for this process */
289 HANDLE mqi_lock
; /* mutex lock */
290 HANDLE mqi_wait
; /* and condition variable */
293 #define MQI_MAGIC 0x98765432UL
295 #define MSGSIZE(i) roundup((i), sizeof(long))
297 #define MAX_TRIES 10 /* for waiting for initialization */
299 struct mq_attr defattr
= { 0, 10, 8192, 0 }; /* Linux defaults. */
301 extern "C" _off64_t
lseek64 (int, _off64_t
, int);
302 extern "C" void *mmap64 (void *, size_t, int, int, int, _off64_t
);
305 mq_open (const char *name
, int oflag
, ...)
307 int i
, fd
, nonblock
, created
;
309 _off64_t filesize
= 0;
313 struct __stat64 statbuff
;
314 struct mq_hdr
*mqhdr
;
315 struct msg_hdr
*msghdr
;
316 struct mq_attr
*attr
;
317 struct mq_info
*mqinfo
;
320 size_t len
= strlen (name
);
321 char mqname
[ipc_names
[mqueue
].prefix_len
+ len
];
323 if (!check_path (mqname
, mqueue
, name
, len
))
327 if (efault
.faulted (EFAULT
))
330 oflag
&= (O_CREAT
| O_EXCL
| O_NONBLOCK
);
332 nonblock
= oflag
& O_NONBLOCK
;
333 oflag
&= ~O_NONBLOCK
;
334 mptr
= (int8_t *) MAP_FAILED
;
340 va_start (ap
, oflag
); /* init ap to final named argument */
341 mode
= va_arg (ap
, mode_t
) & ~S_IXUSR
;
342 attr
= va_arg (ap
, struct mq_attr
*);
345 /* Open and specify O_EXCL and user-execute */
346 fd
= open (mqname
, oflag
| O_EXCL
| O_RDWR
, mode
| S_IXUSR
);
349 if (errno
== EEXIST
&& (oflag
& O_EXCL
) == 0)
350 goto exists
; /* already exists, OK */
354 /* First one to create the file initializes it */
357 else if (attr
->mq_maxmsg
<= 0 || attr
->mq_msgsize
<= 0)
362 /* Calculate and set the file size */
363 msgsize
= MSGSIZE (attr
->mq_msgsize
);
364 filesize
= sizeof (struct mq_hdr
)
365 + (attr
->mq_maxmsg
* (sizeof (struct msg_hdr
) + msgsize
));
366 if (lseek64 (fd
, filesize
- 1, SEEK_SET
) == -1)
368 if (write (fd
, "", 1) == -1)
371 /* Memory map the file */
372 mptr
= (int8_t *) mmap64 (NULL
, (size_t) filesize
, PROT_READ
| PROT_WRITE
,
374 if (mptr
== (int8_t *) MAP_FAILED
)
377 /* Allocate one mq_info{} for the queue */
378 if (!(mqinfo
= (struct mq_info
*) malloc (sizeof (struct mq_info
))))
380 mqinfo
->mqi_hdr
= mqhdr
= (struct mq_hdr
*) mptr
;
381 mqinfo
->mqi_magic
= MQI_MAGIC
;
382 mqinfo
->mqi_flags
= nonblock
;
384 /* Initialize header at beginning of file */
385 /* Create free list with all messages on it */
386 mqhdr
->mqh_attr
.mq_flags
= 0;
387 mqhdr
->mqh_attr
.mq_maxmsg
= attr
->mq_maxmsg
;
388 mqhdr
->mqh_attr
.mq_msgsize
= attr
->mq_msgsize
;
389 mqhdr
->mqh_attr
.mq_curmsgs
= 0;
390 mqhdr
->mqh_nwait
= 0;
392 if (!AllocateLocallyUniqueId (&luid
))
397 __small_sprintf (mqhdr
->mqh_uname
, "%016X%08x%08x",
398 hash_path_name (0,mqname
),
399 luid
.HighPart
, luid
.LowPart
);
401 index
= sizeof (struct mq_hdr
);
402 mqhdr
->mqh_free
= index
;
403 for (i
= 0; i
< attr
->mq_maxmsg
- 1; i
++)
405 msghdr
= (struct msg_hdr
*) &mptr
[index
];
406 index
+= sizeof (struct msg_hdr
) + msgsize
;
407 msghdr
->msg_next
= index
;
409 msghdr
= (struct msg_hdr
*) &mptr
[index
];
410 msghdr
->msg_next
= 0; /* end of free list */
412 /* Initialize mutex & condition variable */
413 i
= ipc_mutex_init (&mqinfo
->mqi_lock
, mqhdr
->mqh_uname
);
417 i
= ipc_cond_init (&mqinfo
->mqi_wait
, mqhdr
->mqh_uname
);
421 /* Initialization complete, turn off user-execute bit */
422 if (fchmod (fd
, mode
) == -1)
425 return ((mqd_t
) mqinfo
);
429 /* Open the file then memory map */
430 if ((fd
= open (mqname
, O_RDWR
)) < 0)
432 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
436 /* Make certain initialization is complete */
437 for (i
= 0; i
< MAX_TRIES
; i
++)
439 if (stat64 (mqname
, &statbuff
) == -1)
441 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
448 if ((statbuff
.st_mode
& S_IXUSR
) == 0)
454 set_errno (ETIMEDOUT
);
458 filesize
= statbuff
.st_size
;
459 mptr
= (int8_t *) mmap64 (NULL
, (size_t) filesize
, PROT_READ
| PROT_WRITE
,
461 if (mptr
== (int8_t *) MAP_FAILED
)
465 /* Allocate one mq_info{} for each open */
466 if (!(mqinfo
= (struct mq_info
*) malloc (sizeof (struct mq_info
))))
468 mqinfo
->mqi_hdr
= mqhdr
= (struct mq_hdr
*) mptr
;
469 mqinfo
->mqi_magic
= MQI_MAGIC
;
470 mqinfo
->mqi_flags
= nonblock
;
472 /* Initialize mutex & condition variable */
473 i
= ipc_mutex_init (&mqinfo
->mqi_lock
, mqhdr
->mqh_uname
);
477 i
= ipc_cond_init (&mqinfo
->mqi_wait
, mqhdr
->mqh_uname
);
481 return (mqd_t
) mqinfo
;
486 /* Don't let following function calls change errno */
491 if (mptr
!= (int8_t *) MAP_FAILED
)
492 munmap((void *) mptr
, (size_t) filesize
);
500 mq_getattr (mqd_t mqd
, struct mq_attr
*mqstat
)
503 struct mq_hdr
*mqhdr
;
504 struct mq_attr
*attr
;
505 struct mq_info
*mqinfo
;
508 if (efault
.faulted (EBADF
))
511 mqinfo
= (struct mq_info
*) mqd
;
512 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
517 mqhdr
= mqinfo
->mqi_hdr
;
518 attr
= &mqhdr
->mqh_attr
;
519 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
524 mqstat
->mq_flags
= mqinfo
->mqi_flags
; /* per-open */
525 mqstat
->mq_maxmsg
= attr
->mq_maxmsg
; /* remaining three per-queue */
526 mqstat
->mq_msgsize
= attr
->mq_msgsize
;
527 mqstat
->mq_curmsgs
= attr
->mq_curmsgs
;
529 ipc_mutex_unlock (mqinfo
->mqi_lock
);
534 mq_setattr (mqd_t mqd
, const struct mq_attr
*mqstat
, struct mq_attr
*omqstat
)
537 struct mq_hdr
*mqhdr
;
538 struct mq_attr
*attr
;
539 struct mq_info
*mqinfo
;
542 if (efault
.faulted (EBADF
))
545 mqinfo
= (struct mq_info
*) mqd
;
546 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
551 mqhdr
= mqinfo
->mqi_hdr
;
552 attr
= &mqhdr
->mqh_attr
;
553 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
561 omqstat
->mq_flags
= mqinfo
->mqi_flags
; /* previous attributes */
562 omqstat
->mq_maxmsg
= attr
->mq_maxmsg
;
563 omqstat
->mq_msgsize
= attr
->mq_msgsize
;
564 omqstat
->mq_curmsgs
= attr
->mq_curmsgs
; /* and current status */
567 if (mqstat
->mq_flags
& O_NONBLOCK
)
568 mqinfo
->mqi_flags
|= O_NONBLOCK
;
570 mqinfo
->mqi_flags
&= ~O_NONBLOCK
;
572 ipc_mutex_unlock (mqinfo
->mqi_lock
);
577 mq_notify (mqd_t mqd
, const struct sigevent
*notification
)
581 struct mq_hdr
*mqhdr
;
582 struct mq_info
*mqinfo
;
585 if (efault
.faulted (EBADF
))
588 mqinfo
= (struct mq_info
*) mqd
;
589 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
594 mqhdr
= mqinfo
->mqi_hdr
;
595 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
604 if (mqhdr
->mqh_pid
== pid
)
605 mqhdr
->mqh_pid
= 0; /* unregister calling process */
609 if (mqhdr
->mqh_pid
!= 0)
611 if (kill (mqhdr
->mqh_pid
, 0) != -1 || errno
!= ESRCH
)
614 ipc_mutex_unlock (mqinfo
->mqi_lock
);
618 mqhdr
->mqh_pid
= pid
;
619 mqhdr
->mqh_event
= *notification
;
621 ipc_mutex_unlock (mqinfo
->mqi_lock
);
626 _mq_send (mqd_t mqd
, const char *ptr
, size_t len
, unsigned int prio
,
627 const struct timespec
*abstime
)
630 long index
, freeindex
;
632 struct sigevent
*sigev
;
633 struct mq_hdr
*mqhdr
;
634 struct mq_attr
*attr
;
635 struct msg_hdr
*msghdr
, *nmsghdr
, *pmsghdr
;
636 struct mq_info
*mqinfo
;
639 if (efault
.faulted (EBADF
))
642 mqinfo
= (struct mq_info
*) mqd
;
643 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
648 if (prio
> MQ_PRIO_MAX
)
654 mqhdr
= mqinfo
->mqi_hdr
; /* struct pointer */
655 mptr
= (int8_t *) mqhdr
; /* byte pointer */
656 attr
= &mqhdr
->mqh_attr
;
657 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
663 if (len
> (size_t) attr
->mq_msgsize
)
665 set_errno (EMSGSIZE
);
668 if (attr
->mq_curmsgs
== 0)
670 if (mqhdr
->mqh_pid
!= 0 && mqhdr
->mqh_nwait
== 0)
672 sigev
= &mqhdr
->mqh_event
;
673 if (sigev
->sigev_notify
== SIGEV_SIGNAL
)
674 sigqueue (mqhdr
->mqh_pid
, sigev
->sigev_signo
, sigev
->sigev_value
);
675 mqhdr
->mqh_pid
= 0; /* unregister */
678 else if (attr
->mq_curmsgs
>= attr
->mq_maxmsg
)
681 if (mqinfo
->mqi_flags
& O_NONBLOCK
)
686 /* Wait for room for one message on the queue */
687 while (attr
->mq_curmsgs
>= attr
->mq_maxmsg
)
688 ipc_cond_timedwait (mqinfo
->mqi_wait
, mqinfo
->mqi_lock
, abstime
);
691 /* nmsghdr will point to new message */
692 if ((freeindex
= mqhdr
->mqh_free
) == 0)
693 api_fatal ("mq_send: curmsgs = %ld; free = 0", attr
->mq_curmsgs
);
695 nmsghdr
= (struct msg_hdr
*) &mptr
[freeindex
];
696 nmsghdr
->msg_prio
= prio
;
697 nmsghdr
->msg_len
= len
;
698 memcpy (nmsghdr
+ 1, ptr
, len
); /* copy message from caller */
699 mqhdr
->mqh_free
= nmsghdr
->msg_next
; /* new freelist head */
701 /* Find right place for message in linked list */
702 index
= mqhdr
->mqh_head
;
703 pmsghdr
= (struct msg_hdr
*) &(mqhdr
->mqh_head
);
706 msghdr
= (struct msg_hdr
*) &mptr
[index
];
707 if (prio
> msghdr
->msg_prio
)
709 nmsghdr
->msg_next
= index
;
710 pmsghdr
->msg_next
= freeindex
;
713 index
= msghdr
->msg_next
;
718 /* Queue was empty or new goes at end of list */
719 pmsghdr
->msg_next
= freeindex
;
720 nmsghdr
->msg_next
= 0;
722 /* Wake up anyone blocked in mq_receive waiting for a message */
723 if (attr
->mq_curmsgs
== 0)
724 ipc_cond_signal (mqinfo
->mqi_wait
);
727 ipc_mutex_unlock (mqinfo
->mqi_lock
);
731 ipc_mutex_unlock (mqinfo
->mqi_lock
);
736 mq_send (mqd_t mqd
, const char *ptr
, size_t len
, unsigned int prio
)
738 return _mq_send (mqd
, ptr
, len
, prio
, NULL
);
742 mq_timedsend (mqd_t mqd
, const char *ptr
, size_t len
, unsigned int prio
,
743 const struct timespec
*abstime
)
745 return _mq_send (mqd
, ptr
, len
, prio
, abstime
);
749 _mq_receive (mqd_t mqd
, char *ptr
, size_t maxlen
, unsigned int *priop
,
750 const struct timespec
*abstime
)
756 struct mq_hdr
*mqhdr
;
757 struct mq_attr
*attr
;
758 struct msg_hdr
*msghdr
;
759 struct mq_info
*mqinfo
;
762 if (efault
.faulted (EBADF
))
765 mqinfo
= (struct mq_info
*) mqd
;
766 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
771 mqhdr
= mqinfo
->mqi_hdr
; /* struct pointer */
772 mptr
= (int8_t *) mqhdr
; /* byte pointer */
773 attr
= &mqhdr
->mqh_attr
;
774 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
780 if (maxlen
< (size_t) attr
->mq_msgsize
)
782 set_errno (EMSGSIZE
);
785 if (attr
->mq_curmsgs
== 0) /* queue is empty */
787 if (mqinfo
->mqi_flags
& O_NONBLOCK
)
792 /* Wait for a message to be placed onto queue */
794 while (attr
->mq_curmsgs
== 0)
795 ipc_cond_timedwait (mqinfo
->mqi_wait
, mqinfo
->mqi_lock
, abstime
);
799 if ((index
= mqhdr
->mqh_head
) == 0)
800 api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr
->mq_curmsgs
);
802 msghdr
= (struct msg_hdr
*) &mptr
[index
];
803 mqhdr
->mqh_head
= msghdr
->msg_next
; /* new head of list */
804 len
= msghdr
->msg_len
;
805 memcpy(ptr
, msghdr
+ 1, len
); /* copy the message itself */
807 *priop
= msghdr
->msg_prio
;
809 /* Just-read message goes to front of free list */
810 msghdr
->msg_next
= mqhdr
->mqh_free
;
811 mqhdr
->mqh_free
= index
;
813 /* Wake up anyone blocked in mq_send waiting for room */
814 if (attr
->mq_curmsgs
== attr
->mq_maxmsg
)
815 ipc_cond_signal (mqinfo
->mqi_wait
);
818 ipc_mutex_unlock (mqinfo
->mqi_lock
);
822 ipc_mutex_unlock (mqinfo
->mqi_lock
);
827 mq_receive (mqd_t mqd
, char *ptr
, size_t maxlen
, unsigned int *priop
)
829 return _mq_receive (mqd
, ptr
, maxlen
, priop
, NULL
);
833 mq_timedreceive (mqd_t mqd
, char *ptr
, size_t maxlen
, unsigned int *priop
,
834 const struct timespec
*abstime
)
836 return _mq_receive (mqd
, ptr
, maxlen
, priop
, abstime
);
842 long msgsize
, filesize
;
843 struct mq_hdr
*mqhdr
;
844 struct mq_attr
*attr
;
845 struct mq_info
*mqinfo
;
848 if (efault
.faulted (EBADF
))
851 mqinfo
= (struct mq_info
*) mqd
;
852 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
857 mqhdr
= mqinfo
->mqi_hdr
;
858 attr
= &mqhdr
->mqh_attr
;
860 if (mq_notify (mqd
, NULL
)) /* unregister calling process */
863 msgsize
= MSGSIZE (attr
->mq_msgsize
);
864 filesize
= sizeof (struct mq_hdr
)
865 + (attr
->mq_maxmsg
* (sizeof (struct msg_hdr
) + msgsize
));
866 if (munmap (mqinfo
->mqi_hdr
, filesize
) == -1)
869 mqinfo
->mqi_magic
= 0; /* just in case */
870 ipc_cond_close (mqinfo
->mqi_wait
);
871 ipc_mutex_close (mqinfo
->mqi_lock
);
877 mq_unlink (const char *name
)
879 size_t len
= strlen (name
);
880 char mqname
[ipc_names
[mqueue
].prefix_len
+ len
];
882 if (!check_path (mqname
, mqueue
, name
, len
))
884 if (unlink (mqname
) == -1)
889 /* POSIX named semaphore implementation. Loosely based on Richard W. STEPHENS
890 implementation as far as sem_open is concerned, but under the hood using
891 the already existing semaphore class in thread.cc. Using a file backed
892 solution allows to implement kernel persistent named semaphores. */
897 unsigned long long hash
;
902 sem_open (const char *name
, int oflag
, ...)
907 unsigned int value
= 0;
908 struct __stat64 statbuff
;
909 sem_t
*sem
= SEM_FAILED
;
911 bool wasopen
= false;
914 size_t len
= strlen (name
);
915 char semname
[ipc_names
[semaphore
].prefix_len
+ len
];
917 if (!check_path (semname
, semaphore
, name
, len
))
921 if (efault
.faulted (EFAULT
))
925 oflag
&= (O_CREAT
| O_EXCL
);
930 va_start (ap
, oflag
); /* init ap to final named argument */
931 mode
= va_arg (ap
, mode_t
) & ~S_IXUSR
;
932 value
= va_arg (ap
, unsigned int);
935 /* Open and specify O_EXCL and user-execute */
936 fd
= open (semname
, oflag
| O_EXCL
| O_RDWR
, mode
| S_IXUSR
);
939 if (errno
== EEXIST
&& (oflag
& O_EXCL
) == 0)
940 goto exists
; /* already exists, OK */
944 /* First one to create the file initializes it. */
945 if (!AllocateLocallyUniqueId (&sf
.luid
))
951 sf
.hash
= hash_path_name (0, semname
);
952 if (write (fd
, &sf
, sizeof sf
) != sizeof sf
)
954 sem
= semaphore::open (sf
.hash
, sf
.luid
, fd
, oflag
, mode
, value
, wasopen
);
955 if (sem
== SEM_FAILED
)
957 /* Initialization complete, turn off user-execute bit */
958 if (fchmod (fd
, mode
) == -1)
960 /* Don't close (fd); */
965 /* Open the file and fetch the semaphore name. */
966 if ((fd
= open (semname
, O_RDWR
)) < 0)
968 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
972 /* Make certain initialization is complete */
973 for (i
= 0; i
< MAX_TRIES
; i
++)
975 if (stat64 (semname
, &statbuff
) == -1)
977 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
984 if ((statbuff
.st_mode
& S_IXUSR
) == 0)
990 set_errno (ETIMEDOUT
);
993 if (file
.lock (fd
, sizeof sf
))
995 if (read (fd
, &sf
, sizeof sf
) != sizeof sf
)
997 sem
= semaphore::open (sf
.hash
, sf
.luid
, fd
, oflag
, mode
, sf
.value
, wasopen
);
999 if (sem
== SEM_FAILED
)
1001 /* If wasopen is set, the semaphore was already opened and we already have
1002 an open file descriptor pointing to the file. This means, we have to
1003 close the file descriptor created in this call. It won't be stored
1010 /* Don't let following function calls change errno */
1016 if (sem
!= SEM_FAILED
)
1017 semaphore::close (sem
);
1023 _sem_close (sem_t
*sem
, bool do_close
)
1029 if (semaphore::getinternal (sem
, &fd
, &sf
.hash
, &sf
.luid
, &sf
.value
) == -1)
1031 if (!file
.lock (fd
, sizeof sf
)
1032 && lseek64 (fd
, 0LL, SEEK_SET
) != (_off64_t
) -1
1033 && write (fd
, &sf
, sizeof sf
) == sizeof sf
)
1034 ret
= do_close
? semaphore::close (sem
) : 0;
1036 /* Don't let following function calls change errno */
1045 sem_close (sem_t
*sem
)
1047 return _sem_close (sem
, true);
1051 sem_unlink (const char *name
)
1053 size_t len
= strlen (name
);
1054 char semname
[ipc_names
[semaphore
].prefix_len
+ len
];
1056 if (!check_path (semname
, semaphore
, name
, len
))
1058 if (unlink (semname
) == -1)
This page took 0.085263 seconds and 6 git commands to generate.