semian 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9844c9c807927ab334939c439c4de127033f5189
4
- data.tar.gz: 5bb4675179a75c585cd05206dbdbf2777002f403
3
+ metadata.gz: 5952a089360c3f99f037dd49e4bfdec80e010d3b
4
+ data.tar.gz: e1862220b675cba619fdddbdde1cccce6c24cd87
5
5
  SHA512:
6
- metadata.gz: 9331e3c0cdd6c41084d9e7a1ec4ed74914ad6b73ec2b7bd90f22b6a9aebb5ec296ca1995c1a02ff28168c73797f7789c4cdbc35f7bdecb39b89faaf284194379
7
- data.tar.gz: 12949dc756b01c369844e6742cebf49626ad1af9a1eb37233e2c4aad4dc5ba4faeb8f9260563fd617e93605870f7ad94acf0a9720dfd6feaf68036a1ca264905
6
+ metadata.gz: 4d6024b8df7dd42b1a6eb517cb8619c8138f20074529a0ffb1f7181dd5d81f9cdeeb9e2b7752ca7d234f400de2880a1d84ff592affc8f92806e2ce15f6d72f28
7
+ data.tar.gz: c7f64858fb8fc83a51b6f43a729cdc2dab9f24633c2a9016b50f3be945921de2893f9bea0eec4ae8419577eb715f108e70bae45ab44134be96b7161e75b6743b
@@ -3,12 +3,12 @@ For core semian resource functions exposed directly to ruby.
3
3
 
4
4
  Functions here are associated with rubyland operations.
5
5
  */
6
-
7
6
  #ifndef SEMIAN_RESOURCE_H
8
7
  #define SEMIAN_RESOURCE_H
9
8
 
10
- #include "semian.h" // FIXME remove this once temporary declarations are removed
11
9
  #include "types.h"
10
+ #include "tickets.h"
11
+ #include "sysv_semaphores.h"
12
12
 
13
13
  // Ruby variables
14
14
  ID id_timeout;
@@ -1,195 +1,5 @@
1
1
  #include "semian.h"
2
2
 
3
- // Time to wait for timed ops to complete
4
- #define INTERNAL_TIMEOUT 5 // seconds
5
-
6
- key_t
7
- generate_key(const char *name)
8
- {
9
- char semset_size_key[20];
10
- char *uniq_id_str;
11
-
12
- // It is necessary for the cardinatily of the semaphore set to be part of the key
13
- // or else sem_get will complain that we have requested an incorrect number of sems
14
- // for the desired key, and have changed the number of semaphores for a given key
15
- sprintf(semset_size_key, "_NUM_SEMS_%d", SI_NUM_SEMAPHORES);
16
- uniq_id_str = malloc(strlen(name)+strlen(semset_size_key)+1);
17
- strcpy(uniq_id_str, name);
18
- strcat(uniq_id_str, semset_size_key);
19
-
20
- union {
21
- unsigned char str[SHA_DIGEST_LENGTH];
22
- key_t key;
23
- } digest;
24
- SHA1((const unsigned char *) uniq_id_str, strlen(uniq_id_str), digest.str);
25
- free(uniq_id_str);
26
- /* TODO: compile-time assertion that sizeof(key_t) > SHA_DIGEST_LENGTH */
27
- return digest.key;
28
- }
29
-
30
- void
31
- raise_semian_syscall_error(const char *syscall, int error_num)
32
- {
33
- rb_raise(eSyscall, "%s failed, errno: %d (%s)", syscall, error_num, strerror(error_num));
34
- }
35
-
36
- void
37
- set_semaphore_permissions(int sem_id, long permissions)
38
- {
39
- union semun sem_opts;
40
- struct semid_ds stat_buf;
41
-
42
- sem_opts.buf = &stat_buf;
43
- semctl(sem_id, 0, IPC_STAT, sem_opts);
44
- if ((stat_buf.sem_perm.mode & 0xfff) != permissions) {
45
- stat_buf.sem_perm.mode &= ~0xfff;
46
- stat_buf.sem_perm.mode |= permissions;
47
- semctl(sem_id, 0, IPC_SET, sem_opts);
48
- }
49
- }
50
-
51
- static const int kInternalTimeout = 5; /* seconds */
52
-
53
- static int
54
- get_max_tickets(int sem_id)
55
- {
56
- int ret = semctl(sem_id, SI_SEM_CONFIGURED_TICKETS, GETVAL);
57
- if (ret == -1) {
58
- rb_raise(eInternal, "error getting max ticket count, errno: %d (%s)", errno, strerror(errno));
59
- }
60
- return ret;
61
- }
62
-
63
- int
64
- perform_semop(int sem_id, short index, short op, short flags, struct timespec *ts)
65
- {
66
- struct sembuf buf = { 0 };
67
-
68
- buf.sem_num = index;
69
- buf.sem_op = op;
70
- buf.sem_flg = flags;
71
-
72
- if (ts) {
73
- return semtimedop(sem_id, &buf, 1, ts);
74
- } else {
75
- return semop(sem_id, &buf, 1);
76
- }
77
- }
78
-
79
- static VALUE
80
- update_ticket_count(update_ticket_count_t *tc)
81
- {
82
- short delta;
83
- struct timespec ts = { 0 };
84
- ts.tv_sec = kInternalTimeout;
85
-
86
- if (get_max_tickets(tc->sem_id) != tc->tickets) {
87
- delta = tc->tickets - get_max_tickets(tc->sem_id);
88
-
89
- if (perform_semop(tc->sem_id, SI_SEM_TICKETS, delta, 0, &ts) == -1) {
90
- rb_raise(eInternal, "error setting ticket count, errno: %d (%s)", errno, strerror(errno));
91
- }
92
-
93
- if (semctl(tc->sem_id, SI_SEM_CONFIGURED_TICKETS, SETVAL, tc->tickets) == -1) {
94
- rb_raise(eInternal, "error updating max ticket count, errno: %d (%s)", errno, strerror(errno));
95
- }
96
- }
97
-
98
- return Qnil;
99
- }
100
-
101
- void
102
- configure_tickets(int sem_id, int tickets, int should_initialize)
103
- {
104
- struct timespec ts = { 0 };
105
- unsigned short init_vals[SI_NUM_SEMAPHORES];
106
- struct timeval start_time, cur_time;
107
- update_ticket_count_t tc;
108
- int state;
109
-
110
- if (should_initialize) {
111
- init_vals[SI_SEM_TICKETS] = init_vals[SI_SEM_CONFIGURED_TICKETS] = tickets;
112
- init_vals[SI_SEM_LOCK] = 1;
113
- if (semctl(sem_id, 0, SETALL, init_vals) == -1) {
114
- raise_semian_syscall_error("semctl()", errno);
115
- }
116
- } else if (tickets > 0) {
117
- /* it's possible that we haven't actually initialized the
118
- semaphore structure yet - wait a bit in that case */
119
- if (get_max_tickets(sem_id) == 0) {
120
- gettimeofday(&start_time, NULL);
121
- while (get_max_tickets(sem_id) == 0) {
122
- usleep(10000); /* 10ms */
123
- gettimeofday(&cur_time, NULL);
124
- if ((cur_time.tv_sec - start_time.tv_sec) > kInternalTimeout) {
125
- rb_raise(eInternal, "timeout waiting for semaphore initialization");
126
- }
127
- }
128
- }
129
-
130
- /*
131
- If the current max ticket count is not the same as the requested ticket
132
- count, we need to resize the count. We do this by adding the delta of
133
- (tickets - current_max_tickets) to the semaphore value.
134
- */
135
- if (get_max_tickets(sem_id) != tickets) {
136
- ts.tv_sec = kInternalTimeout;
137
-
138
- if (perform_semop(sem_id, SI_SEM_LOCK, -1, SEM_UNDO, &ts) == -1) {
139
- raise_semian_syscall_error("error acquiring internal semaphore lock, semtimedop()", errno);
140
- }
141
-
142
- tc.sem_id = sem_id;
143
- tc.tickets = tickets;
144
- rb_protect((VALUE (*)(VALUE)) update_ticket_count, (VALUE) &tc, &state);
145
-
146
- if (perform_semop(sem_id, SI_SEM_LOCK, 1, SEM_UNDO, NULL) == -1) {
147
- raise_semian_syscall_error("error releasing internal semaphore lock, semop()", errno);
148
- }
149
-
150
- if (state) {
151
- rb_jump_tag(state);
152
- }
153
- }
154
- }
155
- }
156
-
157
- int
158
- create_semaphore(int key, long permissions, int *created)
159
- {
160
- int semid = 0;
161
- int flags = 0;
162
-
163
- *created = 0;
164
- flags = IPC_EXCL | IPC_CREAT | permissions;
165
-
166
- semid = semget(key, SI_NUM_SEMAPHORES, flags);
167
- if (semid >= 0) {
168
- *created = 1;
169
- } else if (semid == -1 && errno == EEXIST) {
170
- flags &= ~IPC_EXCL;
171
- semid = semget(key, SI_NUM_SEMAPHORES, flags);
172
- }
173
- return semid;
174
- }
175
-
176
- void *
177
- acquire_semaphore_without_gvl(void *p)
178
- {
179
- semian_resource_t *res = (semian_resource_t *) p;
180
- res->error = 0;
181
- if (perform_semop(res->sem_id, SI_SEM_TICKETS, -1, SEM_UNDO, &res->timeout) == -1) {
182
- res->error = errno;
183
- }
184
- return NULL;
185
- }
186
-
187
- int
188
- get_semaphore(int key)
189
- {
190
- return semget(key, SI_NUM_SEMAPHORES, 0);
191
- }
192
-
193
3
  void Init_semian()
194
4
  {
195
5
  VALUE cSemian, cResource;
@@ -7,61 +7,8 @@ Implements Init_semian, which is used as C/Ruby entrypoint.
7
7
  #ifndef SEMIAN_H
8
8
  #define SEMIAN_H
9
9
 
10
- // System includes
11
- #include <errno.h>
12
- #include <string.h>
13
- #include <stdio.h>
14
-
15
- // 3rd party includes
16
- #include <openssl/sha.h>
17
- #include <ruby.h>
18
- #include <ruby/util.h>
19
- #include <ruby/io.h>
20
-
21
- //semian includes
22
- #include "types.h"
23
10
  #include "resource.h"
24
11
 
25
- // FIXME: This is needed here temporarily
26
- // Defines for ruby threading primitives
27
- #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_RUBY_THREAD_H)
28
- // 2.0
29
- #include <ruby/thread.h>
30
- #define WITHOUT_GVL(fn,a,ubf,b) rb_thread_call_without_gvl((fn),(a),(ubf),(b))
31
- #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
32
- // 1.9
33
- typedef VALUE (*my_blocking_fn_t)(void*);
34
- #define WITHOUT_GVL(fn,a,ubf,b) rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
35
- #endif
36
-
37
- VALUE eSyscall, eTimeout, eInternal;
38
-
39
12
  void Init_semian();
40
13
 
41
- // FIXME: These are needed here temporarily while we move functions around
42
- // Will be removed once there are new header files that the should belong to.
43
- void
44
- configure_tickets(int sem_id, int tickets, int should_initialize);
45
-
46
- key_t
47
- generate_key(const char *name);
48
-
49
- void
50
- set_semaphore_permissions(int sem_id, long permissions);
51
-
52
- int
53
- create_semaphore(int key, long permissions, int *created);
54
-
55
- int
56
- get_semaphore(int key);
57
-
58
- void
59
- raise_semian_syscall_error(const char *syscall, int error_num);
60
-
61
- int
62
- perform_semop(int sem_id, short index, short op, short flags, struct timespec *ts);
63
-
64
- void *
65
- acquire_semaphore_without_gvl(void *p);
66
-
67
14
  #endif //SEMIAN_H
@@ -0,0 +1,128 @@
1
+ #include <sysv_semaphores.h>
2
+
3
+ void
4
+ raise_semian_syscall_error(const char *syscall, int error_num)
5
+ {
6
+ rb_raise(eSyscall, "%s failed, errno: %d (%s)", syscall, error_num, strerror(error_num));
7
+ }
8
+
9
+ key_t
10
+ generate_key(const char *name)
11
+ {
12
+ char semset_size_key[20];
13
+ char *uniq_id_str;
14
+
15
+ // It is necessary for the cardinatily of the semaphore set to be part of the key
16
+ // or else sem_get will complain that we have requested an incorrect number of sems
17
+ // for the desired key, and have changed the number of semaphores for a given key
18
+ sprintf(semset_size_key, "_NUM_SEMS_%d", SI_NUM_SEMAPHORES);
19
+ uniq_id_str = malloc(strlen(name)+strlen(semset_size_key)+1);
20
+ strcpy(uniq_id_str, name);
21
+ strcat(uniq_id_str, semset_size_key);
22
+
23
+ union {
24
+ unsigned char str[SHA_DIGEST_LENGTH];
25
+ key_t key;
26
+ } digest;
27
+ SHA1((const unsigned char *) uniq_id_str, strlen(uniq_id_str), digest.str);
28
+ free(uniq_id_str);
29
+ /* TODO: compile-time assertion that sizeof(key_t) > SHA_DIGEST_LENGTH */
30
+ return digest.key;
31
+ }
32
+
33
+ void
34
+ set_semaphore_permissions(int sem_id, long permissions)
35
+ {
36
+ union semun sem_opts;
37
+ struct semid_ds stat_buf;
38
+
39
+ sem_opts.buf = &stat_buf;
40
+ semctl(sem_id, 0, IPC_STAT, sem_opts);
41
+ if ((stat_buf.sem_perm.mode & 0xfff) != permissions) {
42
+ stat_buf.sem_perm.mode &= ~0xfff;
43
+ stat_buf.sem_perm.mode |= permissions;
44
+ semctl(sem_id, 0, IPC_SET, sem_opts);
45
+ }
46
+ }
47
+
48
+ int
49
+ create_semaphore(int key, long permissions, int *created)
50
+ {
51
+ int semid = 0;
52
+ int flags = 0;
53
+
54
+ *created = 0;
55
+ flags = IPC_EXCL | IPC_CREAT | permissions;
56
+
57
+ semid = semget(key, SI_NUM_SEMAPHORES, flags);
58
+ if (semid >= 0) {
59
+ *created = 1;
60
+ } else if (semid == -1 && errno == EEXIST) {
61
+ flags &= ~IPC_EXCL;
62
+ semid = semget(key, SI_NUM_SEMAPHORES, flags);
63
+ }
64
+ return semid;
65
+ }
66
+
67
+
68
+ int
69
+ perform_semop(int sem_id, short index, short op, short flags, struct timespec *ts)
70
+ {
71
+ struct sembuf buf = { 0 };
72
+
73
+ buf.sem_num = index;
74
+ buf.sem_op = op;
75
+ buf.sem_flg = flags;
76
+
77
+ if (ts) {
78
+ return semtimedop(sem_id, &buf, 1, ts);
79
+ } else {
80
+ return semop(sem_id, &buf, 1);
81
+ }
82
+ }
83
+
84
+ int
85
+ get_max_tickets(int sem_id)
86
+ {
87
+ int ret = semctl(sem_id, SI_SEM_CONFIGURED_TICKETS, GETVAL);
88
+ if (ret == -1) {
89
+ rb_raise(eInternal, "error getting max ticket count, errno: %d (%s)", errno, strerror(errno));
90
+ }
91
+ return ret;
92
+ }
93
+
94
+ void
95
+ sem_meta_lock(int sem_id)
96
+ {
97
+ struct timespec ts = { 0 };
98
+ ts.tv_sec = INTERNAL_TIMEOUT;
99
+
100
+ if (perform_semop(sem_id, SI_SEM_LOCK, -1, SEM_UNDO, &ts) == -1) {
101
+ raise_semian_syscall_error("error acquiring internal semaphore lock, semtimedop()", errno);
102
+ }
103
+ }
104
+
105
+ void
106
+ sem_meta_unlock(int sem_id)
107
+ {
108
+ if (perform_semop(sem_id, SI_SEM_LOCK, 1, SEM_UNDO, NULL) == -1) {
109
+ raise_semian_syscall_error("error releasing internal semaphore lock, semop()", errno);
110
+ }
111
+ }
112
+
113
+ int
114
+ get_semaphore(int key)
115
+ {
116
+ return semget(key, SI_NUM_SEMAPHORES, 0);
117
+ }
118
+
119
+ void *
120
+ acquire_semaphore_without_gvl(void *p)
121
+ {
122
+ semian_resource_t *res = (semian_resource_t *) p;
123
+ res->error = 0;
124
+ if (perform_semop(res->sem_id, SI_SEM_TICKETS, -1, SEM_UNDO, &res->timeout) == -1) {
125
+ res->error = errno;
126
+ }
127
+ return NULL;
128
+ }
@@ -0,0 +1,78 @@
1
+ /*
2
+ For manipulating the semian's semaphore set
3
+
4
+ Semian semaphore operations and initialization,
5
+ and functions associated directly weth semops.
6
+ */
7
+ #ifndef SEMIAN_SEMSET_H
8
+ #define SEMIAN_SEMSET_H
9
+
10
+ #include <errno.h>
11
+ #include <stdio.h>
12
+ #include <string.h>
13
+
14
+ #include <openssl/sha.h>
15
+ #include <ruby.h>
16
+ #include <ruby/util.h>
17
+ #include <ruby/io.h>
18
+
19
+ #include <types.h>
20
+
21
+ // Defines for ruby threading primitives
22
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_RUBY_THREAD_H)
23
+ // 2.0
24
+ #include <ruby/thread.h>
25
+ #define WITHOUT_GVL(fn,a,ubf,b) rb_thread_call_without_gvl((fn),(a),(ubf),(b))
26
+ #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
27
+ // 1.9
28
+ typedef VALUE (*my_blocking_fn_t)(void*);
29
+ #define WITHOUT_GVL(fn,a,ubf,b) rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
30
+ #endif
31
+
32
+ // Time to wait for timed ops to complete
33
+ #define INTERNAL_TIMEOUT 5 /* seconds */
34
+
35
+ VALUE eSyscall, eTimeout, eInternal;
36
+
37
+ // Helper for syscall verbose debugging
38
+ void
39
+ raise_semian_syscall_error(const char *syscall, int error_num);
40
+
41
+ // Genurates a unique key for the semaphore from the resource id
42
+ key_t
43
+ generate_key(const char *name);
44
+
45
+ // Set semaphore UNIX octal permissions
46
+ void
47
+ set_semaphore_permissions(int sem_id, long permissions);
48
+
49
+ // Create a new sysV IPC semaphore set
50
+ int
51
+ create_semaphore(int key, long permissions, int *created);
52
+
53
+ // Wrapper to performs a semop call
54
+ // The call may be timed or untimed
55
+ int
56
+ perform_semop(int sem_id, short index, short op, short flags, struct timespec *ts);
57
+
58
+ // Retrieve the current number of tickets in a semaphore by its semaphore index
59
+ int
60
+ get_max_tickets(int sem_id);
61
+
62
+ // Obtain an exclusive lock on the semaphore set critical section
63
+ void
64
+ sem_meta_lock(int sem_id);
65
+
66
+ // Release an exclusive lock on the semaphore set critical section
67
+ void
68
+ sem_meta_unlock(int sem_id);
69
+
70
+ // Retrieve a semaphore's ID from its key
71
+ int
72
+ get_semaphore(int key);
73
+
74
+ // Decrements the ticket semaphore within the semaphore set
75
+ void *
76
+ acquire_semaphore_without_gvl(void *p);
77
+
78
+ #endif // SEMIAN_SEMSET_H
@@ -0,0 +1,72 @@
1
+ #include <tickets.h>
2
+
3
+ VALUE
4
+ update_ticket_count(update_ticket_count_t *tc)
5
+ {
6
+ short delta;
7
+ struct timespec ts = { 0 };
8
+ ts.tv_sec = INTERNAL_TIMEOUT;
9
+
10
+ if (get_max_tickets(tc->sem_id) != tc->tickets) {
11
+ delta = tc->tickets - get_max_tickets(tc->sem_id);
12
+
13
+ if (perform_semop(tc->sem_id, SI_SEM_TICKETS, delta, 0, &ts) == -1) {
14
+ rb_raise(eInternal, "error setting ticket count, errno: %d (%s)", errno, strerror(errno));
15
+ }
16
+
17
+ if (semctl(tc->sem_id, SI_SEM_CONFIGURED_TICKETS, SETVAL, tc->tickets) == -1) {
18
+ rb_raise(eInternal, "error updating max ticket count, errno: %d (%s)", errno, strerror(errno));
19
+ }
20
+ }
21
+
22
+ return Qnil;
23
+ }
24
+
25
+ void
26
+ configure_tickets(int sem_id, int tickets, int should_initialize)
27
+ {
28
+ unsigned short init_vals[SI_NUM_SEMAPHORES];
29
+ struct timeval start_time, cur_time;
30
+ update_ticket_count_t tc;
31
+ int state;
32
+
33
+ if (should_initialize) {
34
+ init_vals[SI_SEM_TICKETS] = init_vals[SI_SEM_CONFIGURED_TICKETS] = tickets;
35
+ init_vals[SI_SEM_LOCK] = 1;
36
+ if (semctl(sem_id, 0, SETALL, init_vals) == -1) {
37
+ raise_semian_syscall_error("semctl()", errno);
38
+ }
39
+ } else if (tickets > 0) {
40
+ /* it's possible that we haven't actually initialized the
41
+ semaphore structure yet - wait a bit in that case */
42
+ if (get_max_tickets(sem_id) == 0) {
43
+ gettimeofday(&start_time, NULL);
44
+ while (get_max_tickets(sem_id) == 0) {
45
+ usleep(10000); /* 10ms */
46
+ gettimeofday(&cur_time, NULL);
47
+ if ((cur_time.tv_sec - start_time.tv_sec) > INTERNAL_TIMEOUT) {
48
+ rb_raise(eInternal, "timeout waiting for semaphore initialization");
49
+ }
50
+ }
51
+ }
52
+
53
+ /*
54
+ If the current max ticket count is not the same as the requested ticket
55
+ count, we need to resize the count. We do this by adding the delta of
56
+ (tickets - current_max_tickets) to the semaphore value.
57
+ */
58
+ if (get_max_tickets(sem_id) != tickets) {
59
+ sem_meta_lock(sem_id);
60
+
61
+ tc.sem_id = sem_id;
62
+ tc.tickets = tickets;
63
+ rb_protect((VALUE (*)(VALUE)) update_ticket_count, (VALUE) &tc, &state);
64
+
65
+ sem_meta_unlock(sem_id);
66
+
67
+ if (state) {
68
+ rb_jump_tag(state);
69
+ }
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,17 @@
1
+ /*
2
+ For logic specific to manipulating semian ticket counts
3
+ */
4
+ #ifndef SEMIAN_TICKETS_H
5
+ #define SEMIAN_TICKETS_H
6
+
7
+ #include <sysv_semaphores.h>
8
+
9
+ // Update the ticket count for static ticket tracking
10
+ VALUE
11
+ update_ticket_count(update_ticket_count_t *tc);
12
+
13
+ // Set initial ticket values upon resource creation
14
+ void
15
+ configure_tickets(int sem_id, int tickets, int should_initialize);
16
+
17
+ #endif // SEMIAN_TICKETS_H
@@ -1,3 +1,3 @@
1
1
  module Semian
2
- VERSION = '0.6.1'
2
+ VERSION = '0.6.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Francis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-02-15 00:00:00.000000000 Z
12
+ date: 2017-02-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
@@ -137,6 +137,10 @@ files:
137
137
  - ext/semian/resource.h
138
138
  - ext/semian/semian.c
139
139
  - ext/semian/semian.h
140
+ - ext/semian/sysv_semaphores.c
141
+ - ext/semian/sysv_semaphores.h
142
+ - ext/semian/tickets.c
143
+ - ext/semian/tickets.h
140
144
  - ext/semian/types.h
141
145
  - lib/semian.rb
142
146
  - lib/semian/adapter.rb