Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / system / cross_process_sem.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation.  See file COPYING.
12 *
13 */
14
15 #include "cross_process_sem.h"
16
17 #include <errno.h>
18 #include <semaphore.h>
19 #include <stdlib.h>
20 #include <sys/mman.h>
21
22 /* We put our cross-process semaphore into a page of memory mapped with mmap. */
23 struct cross_process_sem_data_t
24 {
25   sem_t sem;
26 };
27
28 /* A factory function is a good choice here because we want to be able to
29  * return an error code. It does force heap allocation, but that is the
30  * easiest way to use synchronization primitives anyway. Most programmers don't
31  * care about destroying semaphores before the process finishes. It's pretty
32  * difficult to get it right and there is usually no benefit.
33  */
34 int CrossProcessSem::
35 create(int initial_val, CrossProcessSem** res)
36 {
37   struct cross_process_sem_data_t *data = static_cast < cross_process_sem_data_t*> (
38     mmap(NULL, sizeof(struct cross_process_sem_data_t),
39        PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0));
40   if (data == MAP_FAILED) {
41     int err = errno;
42     return err;
43   }
44   int ret = sem_init(&data->sem, 1, initial_val);
45   if (ret) {
46     return ret;
47   }
48   *res = new CrossProcessSem(data);
49   return 0;
50 }
51
52 CrossProcessSem::
53 ~CrossProcessSem()
54 {
55   munmap(m_data, sizeof(struct cross_process_sem_data_t));
56   m_data = NULL;
57 }
58
59 void CrossProcessSem::
60 wait()
61 {
62   while(true) {
63     int ret = sem_wait(&m_data->sem);
64     if (ret == 0)
65       return;
66     int err = errno;
67     if (err == -EINTR)
68       continue;
69     abort();
70   }
71 }
72
73 void CrossProcessSem::
74 post()
75 {
76   int ret = sem_post(&m_data->sem);
77   if (ret == -1) {
78     abort();
79   }
80 }
81
82 int CrossProcessSem::
83 reinit(int dval)
84 {
85   if (dval < 0)
86     return -EINVAL;
87   int cval;
88   if (sem_getvalue(&m_data->sem, &cval) == -1)
89     return errno;
90   if (cval < dval) {
91     int diff = dval - cval;
92     for (int i = 0; i < diff; ++i)
93       sem_post(&m_data->sem);
94   }
95   else {
96     int diff = cval - dval;
97     for (int i = 0; i < diff; ++i)
98       sem_wait(&m_data->sem);
99   }
100   return 0;
101 }
102
103 CrossProcessSem::
104 CrossProcessSem(struct cross_process_sem_data_t *data)
105   : m_data(data)
106 {
107 }