|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 #include "sema.h" |
|
22 |
|
23 // OS specific headers |
|
24 #ifdef WIN32 |
|
25 #include <windows.h> |
|
26 #include <tlhelp32.h> |
|
27 #else |
|
28 #include <semaphore.h> |
|
29 #include <sys/types.h> |
|
30 #include <signal.h> |
|
31 #include <fcntl.h> |
|
32 #include <time.h> |
|
33 #endif |
|
34 |
|
35 #include <unistd.h> |
|
36 |
|
37 |
|
38 void sema_create(sbs_semaphore *s) |
|
39 { |
|
40 #ifdef WIN32 |
|
41 s->handle = CreateSemaphore(NULL, 1, 1, s->name); |
|
42 if (s->handle) |
|
43 CloseHandle(s->handle); |
|
44 else |
|
45 error("unable to create semaphore %s", s->name); |
|
46 #else |
|
47 s->handle = sem_open(s->name, O_CREAT | O_EXCL, 0644, 1); |
|
48 |
|
49 if (s->handle == SEM_FAILED) |
|
50 { |
|
51 sem_close(s->handle); |
|
52 error("unable to create semaphore %s", s->name); |
|
53 } |
|
54 sem_close(s->handle); |
|
55 #endif |
|
56 } |
|
57 |
|
58 void sema_destroy(sbs_semaphore *s) |
|
59 { |
|
60 #ifdef WIN32 |
|
61 /* can't destroy a windows semaphore... */ |
|
62 #else |
|
63 if (sem_unlink(s->name) != 0) |
|
64 error("unable to unlink semaphore", s->name); |
|
65 #endif |
|
66 } |
|
67 |
|
68 |
|
69 int sema_wait(sbs_semaphore *s) |
|
70 { |
|
71 /* try and open the semaphore now */ |
|
72 #ifdef WIN32 |
|
73 s->handle = CreateSemaphore(NULL, 1, 1, s->name); |
|
74 if (!s->handle) |
|
75 { |
|
76 error("unable to open semaphore %s", s->name); |
|
77 return -2; |
|
78 } |
|
79 #else |
|
80 struct timespec tmout; |
|
81 |
|
82 s->handle = sem_open(s->name, 0); |
|
83 |
|
84 if (s->handle == SEM_FAILED) |
|
85 { |
|
86 sem_close(s->handle); |
|
87 error("unable to open semaphore %s\n", s->name); |
|
88 return -2; |
|
89 } |
|
90 #endif |
|
91 |
|
92 /* wait for the semaphore to be free [timeout if it takes too long] */ |
|
93 int timedOutFlag = 0; |
|
94 int semcount = 0; |
|
95 #ifdef WIN32 |
|
96 timedOutFlag = (WaitForSingleObject(s->handle, s->timeout) != WAIT_OBJECT_0); |
|
97 #else |
|
98 |
|
99 sem_getvalue(s->handle, &semcount); |
|
100 debug("sema: count before wait: %d\n", semcount); |
|
101 debug("sema: timeout: %d\n", s->timeout); |
|
102 |
|
103 if (clock_gettime(CLOCK_REALTIME, &tmout) == -1) |
|
104 { |
|
105 error("sema: clock_gettime failed - can't do timed wait"); |
|
106 return -1; |
|
107 } |
|
108 |
|
109 tmout.tv_sec += (s->timeout / 1000); |
|
110 tmout.tv_nsec += (s->timeout % 1000) * 1000; |
|
111 timedOutFlag = sem_timedwait(s->handle, &tmout); |
|
112 /* roughly speaking the return value indicates timeouts. It also indicated |
|
113 * signals. We are glossing over this for the moment since it isn't really |
|
114 * interesting in this application |
|
115 * */ |
|
116 #endif |
|
117 |
|
118 return timedOutFlag; |
|
119 } |
|
120 |
|
121 |
|
122 void sema_release(sbs_semaphore *s) |
|
123 { |
|
124 /* release the semaphore */ |
|
125 #ifdef WIN32 |
|
126 ReleaseSemaphore(s->handle, 1, NULL); |
|
127 #else |
|
128 sem_post(s->handle); |
|
129 #endif |
|
130 |
|
131 /* clean up */ |
|
132 #ifdef WIN32 |
|
133 CloseHandle(s->handle); |
|
134 #else |
|
135 sem_close(s->handle); |
|
136 #endif |
|
137 } |