]> git.lizzy.rs Git - rudp.git/blob - platform_adpt.c
Switch to CMake
[rudp.git] / platform_adpt.c
1 #include "platform_adpt.h"
2 #include <stdlib.h>
3
4 #ifdef _WIN32
5
6 void PA_NetLibInit()
7 {
8         WSADATA wd;
9         WSAStartup(0x0202, &wd);
10 }
11
12 int PA_Write(PA_HFILE hFile, const void *pBuff, unsigned int size)
13 {
14         DWORD dwWritten;
15         if( ! WriteFile(hFile, pBuff, size, &dwWritten, NULL) )
16                 return -1;
17         return dwWritten;
18 }
19 int PA_Read(PA_HFILE hFile, void *pBuff, unsigned int size)
20 {
21         DWORD dwReaden;
22         if( ! ReadFile(hFile, pBuff, size, &dwReaden, NULL) )
23                 return -1;
24         return dwReaden;
25 }
26
27 PA_HTHREAD PA_ThreadCreate(PA_ThreadRoutine* routine, void* data)
28 {
29         return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)routine, data, 0, NULL);
30 }
31
32 void *PA_ThreadWaitUntilTerminate(PA_HTHREAD hThread) 
33
34         DWORD dwExitCode; 
35         WaitForSingleObject(hThread, INFINITE); 
36         GetExitCodeThread(hThread, &dwExitCode); 
37         return (void*)dwExitCode; 
38 }
39
40 BOOL PA_PipeCreate(PA_PIPE *pHPipeRd, PA_PIPE *pHPipeWrt)
41 {
42         return CreatePipe(pHPipeRd, pHPipeWrt, NULL, 0) == TRUE;
43 }
44 BOOL PA_PipeClose(PA_PIPE hPipe)
45 {
46         return CloseHandle(hPipe);
47 }
48
49 int PA_SocketSetNBlk(PA_SOCKET s, BOOL b)
50 {
51         return ioctlsocket(s, FIONBIO, (u_long*)&b);
52 }
53
54 /***************************** 
55  *      Read-Write Lock
56  *****************************/
57 enum { LOCK_LEVEL_NONE, LOCK_LEVEL_READ, LOCK_LEVEL_WRITE };
58
59 RWLOCK *RWLockCreate()
60 {
61         RWLOCK *pLock = (RWLOCK*)malloc(sizeof(RWLOCK));
62         pLock->m_currentLevel = LOCK_LEVEL_NONE;
63         pLock->m_readerCount    =  pLock->m_writeCount = 0;
64         pLock->m_writerId = 0;
65         //pLock->m_unlockEvent  = CreateEvent( NULL, TRUE, FALSE, NULL );
66         pLock->m_unlockEvent  = CreateEvent( NULL, FALSE, FALSE, NULL );
67         pLock->m_accessMutex  = CreateMutex( NULL, FALSE, NULL );
68         InitializeCriticalSection( &pLock->m_csStateChange );
69         return pLock;
70 }
71
72 BOOL RWLockDestroy(RWLOCK *pLock)
73 {
74         DeleteCriticalSection( &pLock->m_csStateChange );
75         if ( pLock->m_accessMutex ) CloseHandle( pLock->m_accessMutex );
76         if ( pLock->m_unlockEvent ) CloseHandle( pLock->m_unlockEvent );
77         free(pLock);
78         return TRUE;
79 }
80
81 static BOOL _Lock(RWLOCK *pLock, int level, DWORD timeout) 
82 {
83         BOOL  bresult    = TRUE;
84         DWORD waitResult = 0;
85
86         waitResult = WaitForSingleObject( pLock->m_accessMutex, timeout );
87         if ( waitResult != WAIT_OBJECT_0 )  return FALSE;
88
89         if ( level == LOCK_LEVEL_READ && pLock->m_currentLevel != LOCK_LEVEL_WRITE )
90         {
91                 EnterCriticalSection( &pLock->m_csStateChange );
92                 pLock->m_currentLevel = level;
93                 pLock->m_readerCount += 1;
94                 ResetEvent( pLock->m_unlockEvent );
95                 LeaveCriticalSection( &pLock->m_csStateChange );
96         }
97         else if ( level == LOCK_LEVEL_READ && 
98                         pLock->m_currentLevel == LOCK_LEVEL_WRITE )
99         {
100                 waitResult = WaitForSingleObject( pLock->m_unlockEvent, timeout );
101                 if ( waitResult == WAIT_OBJECT_0 )
102                 {
103                         EnterCriticalSection( &pLock->m_csStateChange );
104                         pLock->m_currentLevel = level;
105                         pLock->m_readerCount += 1;
106                         ResetEvent( pLock->m_unlockEvent );
107                         LeaveCriticalSection( &pLock->m_csStateChange );
108                 }
109                 else bresult = FALSE;
110         }
111         else if ( level == LOCK_LEVEL_WRITE && 
112                         pLock->m_currentLevel == LOCK_LEVEL_NONE )
113         {
114                 EnterCriticalSection( &pLock->m_csStateChange );
115                 pLock->m_currentLevel = level;
116                 pLock->m_writerId = GetCurrentThreadId();
117                 pLock->m_writeCount = 1;
118                 ResetEvent( pLock->m_unlockEvent );
119                 LeaveCriticalSection( &pLock->m_csStateChange );
120         }
121         else if ( level == LOCK_LEVEL_WRITE && 
122                         pLock->m_currentLevel != LOCK_LEVEL_NONE )
123         {
124                 DWORD id = GetCurrentThreadId();
125                 if(id == pLock->m_writerId) pLock->m_writeCount++;
126                 else
127                 {
128                         waitResult = WaitForSingleObject( pLock->m_unlockEvent, timeout );
129                         if ( waitResult == WAIT_OBJECT_0 )
130                         {
131                                 EnterCriticalSection( &pLock->m_csStateChange );
132                                 pLock->m_currentLevel = level;
133                                 pLock->m_writerId = GetCurrentThreadId();
134                                 pLock->m_writeCount = 1;
135                                 ResetEvent( pLock->m_unlockEvent );
136                                 LeaveCriticalSection( &pLock->m_csStateChange );
137                         }
138                         else bresult = FALSE;
139                 }
140         }
141
142         ReleaseMutex( pLock->m_accessMutex );
143         return bresult;
144
145 } // lock()
146
147 BOOL RWLockLockR(RWLOCK *pLock, DWORD timeout)
148 {
149         return _Lock(pLock, LOCK_LEVEL_READ, timeout);
150 }
151
152 BOOL RWLockLockW(RWLOCK *pLock, DWORD timeout)
153 {
154        return _Lock(pLock, LOCK_LEVEL_WRITE, timeout); 
155 }
156
157 void RWLockUnlock(RWLOCK *pLock)
158
159         EnterCriticalSection( &pLock->m_csStateChange );
160         if ( pLock->m_currentLevel == LOCK_LEVEL_READ )
161         {
162                 pLock->m_readerCount --;
163                 if ( pLock->m_readerCount == 0 ) 
164                 {
165                         pLock->m_currentLevel = LOCK_LEVEL_NONE;
166                         SetEvent (pLock->m_unlockEvent);
167                 }
168         }
169         else if ( pLock->m_currentLevel == LOCK_LEVEL_WRITE )
170         {
171                 pLock->m_writeCount--;
172                 if(pLock->m_writeCount == 0)
173                 {
174                         pLock->m_currentLevel = LOCK_LEVEL_NONE;
175                         pLock->m_writerId = 0;
176                         SetEvent ( pLock->m_unlockEvent );
177                 }
178         }
179         LeaveCriticalSection( &pLock->m_csStateChange );
180 }
181
182
183 /////////////////////////////////////////////////////////
184 #elif defined(__linux__)
185
186 BOOL PA_EventWaitTimed(PA_EVENT e, DWORD ms)
187 {
188         struct timespec ts;
189
190 #if 0
191         clock_gettime(CLOCK_MONOTONIC, &ts);
192         ts.tv_sec += ms/1000;
193         ts.tv_nsec += (ms%1000)*1000000;
194 #else
195         gettimeofday((struct timeval*)&ts, NULL);
196         ts.tv_nsec *= 1000;
197         ts.tv_sec += ms/1000;
198         ts.tv_nsec += (ms%1000)*1000000;
199         if(ts.tv_nsec > 1000000000) {
200                 ts.tv_nsec -= 1000000000;
201                 ts.tv_sec ++;
202         }
203 #endif
204         return sem_timedwait(e, &ts) == 0;
205 }
206
207 PA_HTHREAD PA_ThreadCreate(PA_ThreadRoutine* routine, void* data)
208 {
209         pthread_t thd;
210         if(pthread_create(&thd, NULL, routine, data) == 0)
211                 return thd;
212         else
213                 return 0;
214 }
215
216 void* PA_ThreadWaitUntilTerminate(PA_HTHREAD hThread) 
217
218         void *tmp; 
219         pthread_join(hThread, &tmp); return tmp; 
220 }
221
222 BOOL PA_PipeCreate(PA_PIPE *pHPipeRd, PA_PIPE *pHPipeWrt)
223 {
224         PA_PIPE fds[2];
225         if(pipe(fds) < 0) return FALSE;
226         *pHPipeRd = fds[0];
227         *pHPipeWrt = fds[1];
228         return TRUE;
229 }
230 BOOL PA_PipeClose(PA_PIPE hPipe)
231 {
232         return 0 == close(hPipe);
233 }
234
235 void PA_Sleep(UINT ms)
236 {
237         struct timeval tv;
238         tv.tv_sec = ms/1000;
239         tv.tv_usec = (ms%1000)*1000;
240         select(0, NULL, NULL, NULL, &tv);
241 }
242
243 DWORD PA_GetTickCount()
244 {
245         struct timespec ts;
246         clock_gettime(CLOCK_MONOTONIC, &ts);
247         return 1000*ts.tv_sec + ts.tv_nsec/1000000;
248 }
249
250 BOOL PA_DeleteFile(const char *fn)
251 {
252         return unlink(fn) == 0; 
253 }
254
255 int PA_SocketSetNBlk(PA_SOCKET s, BOOL b)
256 {
257         int opt = fcntl(s, F_GETFL, &opt, 0);
258         if(b) opt |= O_NONBLOCK;
259         else opt &= ~O_NONBLOCK;
260         return fcntl(s, F_SETFL, opt);
261 }
262
263 /***********************
264  *    Read-Write Lock
265  ***********************/
266 BOOL _RWLockLockR(pthread_rwlock_t *lock, DWORD timeout)
267 {
268         if(timeout == INFINITE)
269                 return pthread_rwlock_rdlock(lock) == 0;
270         else
271         {
272                 while(!pthread_rwlock_tryrdlock(lock) && timeout > 0)
273                 {
274                         usleep(10000);
275                         if(timeout > 10) timeout -= 10;
276                         else return FALSE;
277                 }
278                 return TRUE;
279         }
280 }
281 BOOL _RWLockLockW(pthread_rwlock_t *lock, DWORD timeout)
282 {
283         if(timeout == INFINITE)
284                 return pthread_rwlock_wrlock(lock)==0;
285         else
286         {
287                 while(!pthread_rwlock_trywrlock(lock) && timeout > 0)
288                 {
289                         usleep(10000);
290                         if(timeout > 10) timeout -= 10;
291                         else return FALSE;
292                 }
293                 return TRUE;
294         }
295 }
296
297 #elif defined(ARM_UCOS_LWIP)
298 PA_HTHREAD PA_ThreadCreate(PA_ThreadRoutine* routine, void* data)
299 {
300         //sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
301         return sys_thread_new(NULL, routine, data, 0, 10);
302 }
303 void* PA_ThreadWaitUntilTerminate(PA_HTHREAD hThread)
304 {
305         return NULL;
306 }
307
308 int PA_SocketSetNBlk(PA_SOCKET s, BOOL b)
309 {
310         return lwip_ioctl(s, FIONBIO, (void*)&b);
311 }
312 #endif  //linux
313
314 #ifdef __ANDROID__
315 void android_log(int level, const char *tag, const char *sfmt, ...)
316 {
317         va_list va;
318         char buf[1024];
319         va_start(va, sfmt);
320         vsnprintf(buf, sizeof(buf), sfmt, va);
321         va_end(va);
322         __android_log_write(level, tag, buf);
323 }
324 #endif
325
326 int PA_SocketSetLinger(PA_SOCKET s, int onoff, int linger)
327 {
328         struct linger opt = { onoff, linger };
329         return setsockopt(s, SOL_SOCKET, SO_LINGER, 
330 #ifdef _WIN32
331                 (const char*)&opt, 
332 #else
333                 &opt,
334 #endif
335                 sizeof(opt));
336 }
337
338 #ifdef _DEBUG
339 void dbg_bin(const char *title, const void *p, int size)
340 {
341         int i;
342         unsigned char *byts = (unsigned char*)p;
343         printf(title);
344         for(i=0; i<size; i++)
345         {
346                 printf("%02X ", byts[i]);
347                 if(i>0 && (i&31) == 31) printf("\n");
348         }
349         printf("\n");
350 }
351 #else
352 #define dbg_bin(x, y, z)
353 #endif