2 * Copyright (c) 2013 Larisa Grigore<larisagrigore@gmail.com>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "namespace.h"
29 #include <sys/param.h>
30 #include <sys/types.h>
32 #include <sys/ioctl.h>
37 #include "un-namespace.h"
41 #include "sysvipc_ipc.h"
42 #include "sysvipc_sockets.h"
43 #include "sysvipc_sem.h"
44 #include "sysvipc_shm.h"
45 #include "sysvipc_hash.h"
46 #include "sysvipc_lock.h"
47 #include "sysvipc_lock_generic.h"
49 #define SYSV_MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
50 #define SYSV_MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
51 #define SYSV_MUTEX_DESTROY(x) if (__isthreaded) _pthread_mutex_destroy(x)
55 extern pthread_mutex_t lock_resources;
56 //extern pthread_rwlock_t rwlock_addrs;
57 extern pthread_mutex_t lock_undo;
58 extern struct hashtable *shmaddrs;
60 /* Send the type of the message followed by data. */
62 send_message(int fd, int type, char *data, int size) {
63 _write(fd, &type, sizeof(type));
64 return (send_msg_with_cred(fd, data, size));
67 /* Receive the type of the message that will follow. */
69 receive_type_message(int fd) {
71 int r = _read(fd, &type, sizeof(type));
72 return (r == 0 ? 0 : type);
77 receive_message(int fd, char *data, int size) {
78 _read(fd, data, size);
84 return (daemon_fd == -1 ? 0:1);
88 register_to_daemon(void) {
92 daemon_fd = connect_to_daemon(LISTEN_SOCKET_FILE);
94 flags = _fcntl(daemon_fd, F_GETFD, 0);
95 if (_fcntl(daemon_fd, F_SETFD, flags & FD_CLOEXEC) == -1) {
96 sysv_print_err("fcntl error\n");
100 /* Send a message such that daemon can obtain process credentials.*/
101 send_msg_with_cred(daemon_fd, &test, sizeof(test));
103 sysv_print("register to daemon: sock fd = %d\n", daemon_fd);
108 /* Used in fork case, to avoid deadlocks.
109 * The fork caller acquires all locks before fork and release them
110 * after because the child will have only a thread. If one lock is
111 * taken by another thread than, in the child process, nobody will
115 acquire_locks(void) {
116 struct entries_list *list;
117 struct hashentry *tmp;
118 struct shm_data *data;
119 struct semid_pool *semaptr;
122 SYSV_MUTEX_LOCK(&lock_undo);
123 SYSV_MUTEX_LOCK(&lock_resources);
124 //pthread_rwlock_wrlock(&rwlock_addrs);
126 for (i=0; i<get_hash_size(MAXSIZE); i++) {
127 list = &shmaddrs->entries[i];
128 if (LIST_EMPTY(list))
130 LIST_FOREACH(tmp, list, entry_link) {
131 data = (struct shm_data*)tmp->value;
132 if (data->type == SEMGET) {
133 semaptr = (struct semid_pool *)data->internal;
136 /* There is no need to acquire the mutexes from
137 * each semaphore in the group. It is enough
138 * to acquire the group lock in write mode.
141 sysv_rwlock_wrlock(&semaptr->rwlock);
143 sysv_mutex_lock(&semaptr->mutex);
150 /* Function called by parent after fork to release locks
151 * acquired before fork.
154 parent_release_locks(void) {
155 struct entries_list *list;
156 struct hashentry *tmp;
157 struct shm_data *data;
158 struct semid_pool *semaptr;
161 SYSV_MUTEX_UNLOCK(&lock_undo);
162 SYSV_MUTEX_UNLOCK(&lock_resources);
163 //pthread_rwlock_unlock(&rwlock_addrs);
165 for (i=0; i<get_hash_size(MAXSIZE); i++) {
166 list = &shmaddrs->entries[i];
167 if (LIST_EMPTY(list))
169 LIST_FOREACH(tmp, list, entry_link) {
170 data = (struct shm_data*)tmp->value;
171 if (data->type == SEMGET) {
172 semaptr = (struct semid_pool *)data->internal;
174 sysv_rwlock_unlock(&semaptr->rwlock);
176 sysv_mutex_unlock(&semaptr->mutex);
183 /* Function called by child after fork to release locks
184 * acquired before fork by the parent.
185 * Only locks specific to the address space are released.
186 * Those created in the shared memory are released by the
190 child_release_locks(void) {
191 SYSV_MUTEX_UNLOCK(&lock_undo);
192 SYSV_MUTEX_UNLOCK(&lock_resources);
193 //pthread_rwlock_unlock(&rwlock_addrs);
197 prepare_parent_atfork(void) {
198 /* Function called only if the process has
199 * sysv ipc structures initialized.
204 /* Acquire all locks to be sure that neither one is
205 * held by another thread.
211 parent_atfork(void) {
215 /* Release locks acquired before fork. */
216 parent_release_locks();
224 /* Release locks acquired before fork. */
225 child_release_locks();
226 /* Close the file descriptor used by parent. */
229 /* Register it to daemon too. */
230 if (register_to_daemon() < 0) {
231 sysv_print_err("register to daemon error\n");
235 /* Inform the daemon about each shared memory segment used. */
239 /* The function is called only once, when the process uses for
240 * the first time sysv ipc resources.
246 return (IPC_INITIALIZED);
249 if (register_to_daemon() < 0)
252 /* Add handlers for parent and child when fork is called. */
253 if (_pthread_atfork(prepare_parent_atfork, parent_atfork,
255 sysv_print_err("pthread_atfork error\n");