~ubuntu-branches/ubuntu/vivid/sflphone/vivid

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject/pjlib/src/pj/os_core_win32.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2013-06-30 11:40:56 UTC
  • mfrom: (4.1.18 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130630114056-0np50jkyqo6vnmii
Tags: 1.2.3-2
* changeset_r92d62cfc54732bbbcfff2b1d36c096b120b981a5.diff 
  - fixes automatic endian detection 
* Update Vcs: fixes vcs-field-not-canonical

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: os_core_win32.c 3553 2011-05-05 06:14:19Z nanang $ */
2
 
/* 
3
 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
 
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19
 
 */
20
 
#include <pj/os.h>
21
 
#include <pj/pool.h>
22
 
#include <pj/log.h>
23
 
#include <pj/string.h>
24
 
#include <pj/guid.h>
25
 
#include <pj/rand.h>
26
 
#include <pj/assert.h>
27
 
#include <pj/errno.h>
28
 
#include <pj/except.h>
29
 
#include <stddef.h>
30
 
#include <stdlib.h>
31
 
#include <stdio.h>
32
 
 
33
 
#if defined(PJ_HAS_WINSOCK_H) && PJ_HAS_WINSOCK_H != 0
34
 
#  include <winsock.h>
35
 
#endif
36
 
 
37
 
#if defined(PJ_HAS_WINSOCK2_H) && PJ_HAS_WINSOCK2_H != 0
38
 
#  include <winsock2.h>
39
 
#endif
40
 
 
41
 
/* Activate mutex related logging if PJ_DEBUG_MUTEX is set, otherwise
42
 
 * use default level 6 logging.
43
 
 */
44
 
#if defined(PJ_DEBUG_MUTEX) && PJ_DEBUG_MUTEX
45
 
#   undef PJ_DEBUG
46
 
#   define PJ_DEBUG         1
47
 
#   define LOG_MUTEX(expr)  PJ_LOG(5,expr)
48
 
#else
49
 
#   define LOG_MUTEX(expr)  PJ_LOG(6,expr)
50
 
#endif
51
 
 
52
 
#define THIS_FILE       "os_core_win32.c"
53
 
 
54
 
/*
55
 
 * Implementation of pj_thread_t.
56
 
 */
57
 
struct pj_thread_t
58
 
{
59
 
    char            obj_name[PJ_MAX_OBJ_NAME];
60
 
    HANDLE          hthread;
61
 
    DWORD           idthread;
62
 
    pj_thread_proc *proc;
63
 
    void           *arg;
64
 
 
65
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
66
 
    pj_uint32_t     stk_size;
67
 
    pj_uint32_t     stk_max_usage;
68
 
    char           *stk_start;
69
 
    const char     *caller_file;
70
 
    int             caller_line;
71
 
#endif
72
 
};
73
 
 
74
 
 
75
 
/*
76
 
 * Implementation of pj_mutex_t.
77
 
 */
78
 
struct pj_mutex_t
79
 
{
80
 
#if PJ_WIN32_WINNT >= 0x0400
81
 
    CRITICAL_SECTION    crit;
82
 
#else
83
 
    HANDLE              hMutex;
84
 
#endif
85
 
    char                obj_name[PJ_MAX_OBJ_NAME];
86
 
#if PJ_DEBUG
87
 
    int                 nesting_level;
88
 
    pj_thread_t        *owner;
89
 
#endif
90
 
};
91
 
 
92
 
/*
93
 
 * Implementation of pj_sem_t.
94
 
 */
95
 
typedef struct pj_sem_t
96
 
{
97
 
    HANDLE              hSemaphore;
98
 
    char                obj_name[PJ_MAX_OBJ_NAME];
99
 
} pj_mem_t;
100
 
 
101
 
 
102
 
/*
103
 
 * Implementation of pj_event_t.
104
 
 */
105
 
struct pj_event_t
106
 
{
107
 
    HANDLE              hEvent;
108
 
    char                obj_name[PJ_MAX_OBJ_NAME];
109
 
};
110
 
 
111
 
/*
112
 
 * Implementation of pj_atomic_t.
113
 
 */
114
 
struct pj_atomic_t
115
 
{
116
 
    long value;
117
 
};
118
 
 
119
 
/*
120
 
 * Static global variables.
121
 
 */
122
 
static pj_thread_desc main_thread;
123
 
static long thread_tls_id = -1;
124
 
static pj_mutex_t critical_section_mutex;
125
 
static unsigned atexit_count;
126
 
static void (*atexit_func[32])(void);
127
 
 
128
 
/*
129
 
 * Some static prototypes.
130
 
 */
131
 
static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name);
132
 
 
133
 
 
134
 
/*
135
 
 * pj_init(void).
136
 
 * Init PJLIB!
137
 
 */
138
 
PJ_DEF(pj_status_t) pj_init(void)
139
 
{
140
 
    WSADATA wsa;
141
 
    char dummy_guid[32]; /* use maximum GUID length */
142
 
    pj_str_t guid;
143
 
    pj_status_t rc;
144
 
 
145
 
    /* Init Winsock.. */
146
 
    if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
147
 
        return PJ_RETURN_OS_ERROR(WSAGetLastError());
148
 
    }
149
 
 
150
 
    /* Init this thread's TLS. */
151
 
    if ((rc=pj_thread_init()) != PJ_SUCCESS) {
152
 
        return rc;
153
 
    }
154
 
    
155
 
    /* Init logging */
156
 
    pj_log_init();
157
 
 
158
 
    /* Init random seed. */
159
 
    /* Or probably not. Let application in charge of this */
160
 
    /* pj_srand( GetCurrentProcessId() ); */
161
 
 
162
 
    /* Initialize critical section. */
163
 
    if ((rc=init_mutex(&critical_section_mutex, "pj%p")) != PJ_SUCCESS)
164
 
        return rc;
165
 
 
166
 
    /* Startup GUID. */
167
 
    guid.ptr = dummy_guid;
168
 
    pj_generate_unique_string( &guid );
169
 
 
170
 
    /* Initialize exception ID for the pool. 
171
 
     * Must do so after critical section is configured.
172
 
     */
173
 
    rc = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION);
174
 
    if (rc != PJ_SUCCESS)
175
 
        return rc;
176
 
 
177
 
    /* Startup timestamp */
178
 
#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
179
 
    {
180
 
        pj_timestamp dummy_ts;
181
 
        if ((rc=pj_get_timestamp_freq(&dummy_ts)) != PJ_SUCCESS) {
182
 
            return rc;
183
 
        }
184
 
        if ((rc=pj_get_timestamp(&dummy_ts)) != PJ_SUCCESS) {
185
 
            return rc;
186
 
        }
187
 
    }
188
 
#endif   
189
 
 
190
 
    PJ_LOG(4,(THIS_FILE, "pjlib %s for win32 initialized",
191
 
              PJ_VERSION));
192
 
 
193
 
    return PJ_SUCCESS;
194
 
}
195
 
 
196
 
/*
197
 
 * pj_atexit()
198
 
 */
199
 
PJ_DEF(pj_status_t) pj_atexit(void (*func)(void))
200
 
{
201
 
    if (atexit_count >= PJ_ARRAY_SIZE(atexit_func))
202
 
        return PJ_ETOOMANY;
203
 
 
204
 
    atexit_func[atexit_count++] = func;
205
 
    return PJ_SUCCESS;
206
 
}
207
 
 
208
 
 
209
 
/*
210
 
 * pj_shutdown(void)
211
 
 */
212
 
PJ_DEF(void) pj_shutdown()
213
 
{
214
 
    int i;
215
 
 
216
 
    /* Display stack usage */
217
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
218
 
    {
219
 
        pj_thread_t *rec = (pj_thread_t*)main_thread;
220
 
        PJ_LOG(5,(rec->obj_name, "Main thread stack max usage=%u by %s:%d", 
221
 
                  rec->stk_max_usage, rec->caller_file, rec->caller_line));
222
 
    }
223
 
#endif
224
 
 
225
 
    /* Call atexit() functions */
226
 
    for (i=atexit_count-1; i>=0; --i) {
227
 
        (*atexit_func[i])();
228
 
    }
229
 
    atexit_count = 0;
230
 
 
231
 
    /* Free exception ID */
232
 
    if (PJ_NO_MEMORY_EXCEPTION != -1) {
233
 
        pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION);
234
 
        PJ_NO_MEMORY_EXCEPTION = -1;
235
 
    }
236
 
 
237
 
    /* Destroy PJLIB critical section */
238
 
    pj_mutex_destroy(&critical_section_mutex);
239
 
 
240
 
    /* Free PJLIB TLS */
241
 
    if (thread_tls_id != -1) {
242
 
        pj_thread_local_free(thread_tls_id);
243
 
        thread_tls_id = -1;
244
 
    }
245
 
 
246
 
    /* Clear static variables */
247
 
    pj_errno_clear_handlers();
248
 
 
249
 
    /* Ticket #1132: Assertion when (re)starting PJLIB on different thread */
250
 
    pj_bzero(main_thread, sizeof(main_thread));
251
 
 
252
 
    /* Shutdown Winsock */
253
 
    WSACleanup();
254
 
}
255
 
 
256
 
 
257
 
/*
258
 
 * pj_getpid(void)
259
 
 */
260
 
PJ_DEF(pj_uint32_t) pj_getpid(void)
261
 
{
262
 
    PJ_CHECK_STACK();
263
 
    return GetCurrentProcessId();
264
 
}
265
 
 
266
 
/*
267
 
 * Check if this thread has been registered to PJLIB.
268
 
 */
269
 
PJ_DEF(pj_bool_t) pj_thread_is_registered(void)
270
 
{
271
 
    return pj_thread_local_get(thread_tls_id) != 0;
272
 
}
273
 
 
274
 
 
275
 
/*
276
 
 * Get thread priority value for the thread.
277
 
 */
278
 
PJ_DEF(int) pj_thread_get_prio(pj_thread_t *thread)
279
 
{
280
 
    return GetThreadPriority(thread->hthread);
281
 
}
282
 
 
283
 
 
284
 
/*
285
 
 * Set the thread priority.
286
 
 */
287
 
PJ_DEF(pj_status_t) pj_thread_set_prio(pj_thread_t *thread,  int prio)
288
 
{
289
 
#if PJ_HAS_THREADS
290
 
    PJ_ASSERT_RETURN(thread, PJ_EINVAL);
291
 
    PJ_ASSERT_RETURN(prio>=THREAD_PRIORITY_IDLE && 
292
 
                        prio<=THREAD_PRIORITY_TIME_CRITICAL,
293
 
                     PJ_EINVAL);
294
 
 
295
 
    if (SetThreadPriority(thread->hthread, prio) == FALSE)
296
 
        return PJ_RETURN_OS_ERROR(GetLastError());
297
 
 
298
 
    return PJ_SUCCESS;
299
 
 
300
 
#else
301
 
    PJ_UNUSED_ARG(thread);
302
 
    PJ_UNUSED_ARG(prio);
303
 
    pj_assert("pj_thread_set_prio() called in non-threading mode!");
304
 
    return PJ_EINVALIDOP;
305
 
#endif
306
 
}
307
 
 
308
 
 
309
 
/*
310
 
 * Get the lowest priority value available on this system.
311
 
 */
312
 
PJ_DEF(int) pj_thread_get_prio_min(pj_thread_t *thread)
313
 
{
314
 
    PJ_UNUSED_ARG(thread);
315
 
    return THREAD_PRIORITY_IDLE;
316
 
}
317
 
 
318
 
 
319
 
/*
320
 
 * Get the highest priority value available on this system.
321
 
 */
322
 
PJ_DEF(int) pj_thread_get_prio_max(pj_thread_t *thread)
323
 
{
324
 
    PJ_UNUSED_ARG(thread);
325
 
    return THREAD_PRIORITY_TIME_CRITICAL;
326
 
}
327
 
 
328
 
 
329
 
/*
330
 
 * Get native thread handle
331
 
 */
332
 
PJ_DEF(void*) pj_thread_get_os_handle(pj_thread_t *thread) 
333
 
{
334
 
    PJ_ASSERT_RETURN(thread, NULL);
335
 
 
336
 
#if PJ_HAS_THREADS
337
 
    return thread->hthread;
338
 
#else
339
 
    pj_assert("pj_thread_is_registered() called in non-threading mode!");
340
 
    return NULL;
341
 
#endif
342
 
}
343
 
 
344
 
/*
345
 
 * pj_thread_register(..)
346
 
 */
347
 
PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
348
 
                                         pj_thread_desc desc,
349
 
                                         pj_thread_t **thread_ptr)
350
 
{
351
 
    char stack_ptr;
352
 
    pj_status_t rc;
353
 
    pj_thread_t *thread = (pj_thread_t *)desc;
354
 
    pj_str_t thread_name = pj_str((char*)cstr_thread_name);
355
 
 
356
 
    /* Size sanity check. */
357
 
    if (sizeof(pj_thread_desc) < sizeof(pj_thread_t)) {
358
 
        pj_assert(!"Not enough pj_thread_desc size!");
359
 
        return PJ_EBUG;
360
 
    }
361
 
 
362
 
    /* If a thread descriptor has been registered before, just return it. */
363
 
    if (pj_thread_local_get (thread_tls_id) != 0) {
364
 
        // 2006-02-26 bennylp:
365
 
        //  This wouldn't work in all cases!.
366
 
        //  If thread is created by external module (e.g. sound thread),
367
 
        //  thread may be reused while the pool used for the thread descriptor
368
 
        //  has been deleted by application.
369
 
        //*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);
370
 
        //return PJ_SUCCESS;
371
 
    }
372
 
 
373
 
    /* Initialize and set the thread entry. */
374
 
    pj_bzero(desc, sizeof(struct pj_thread_t));
375
 
    thread->hthread = GetCurrentThread();
376
 
    thread->idthread = GetCurrentThreadId();
377
 
 
378
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
379
 
    thread->stk_start = &stack_ptr;
380
 
    thread->stk_size = 0xFFFFFFFFUL;
381
 
    thread->stk_max_usage = 0;
382
 
#else
383
 
    stack_ptr = '\0';
384
 
#endif
385
 
 
386
 
    if (cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1)
387
 
        pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 
388
 
                         cstr_thread_name, thread->idthread);
389
 
    else
390
 
        pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 
391
 
                         "thr%p", (void*)thread->idthread);
392
 
    
393
 
    rc = pj_thread_local_set(thread_tls_id, thread);
394
 
    if (rc != PJ_SUCCESS)
395
 
        return rc;
396
 
 
397
 
    *thread_ptr = thread;
398
 
    return PJ_SUCCESS;
399
 
}
400
 
 
401
 
/*
402
 
 * pj_thread_init(void)
403
 
 */
404
 
pj_status_t pj_thread_init(void)
405
 
{
406
 
    pj_status_t rc;
407
 
    pj_thread_t *thread;
408
 
 
409
 
    rc = pj_thread_local_alloc(&thread_tls_id);
410
 
    if (rc != PJ_SUCCESS)
411
 
        return rc;
412
 
 
413
 
    return pj_thread_register("thr%p", main_thread, &thread);
414
 
}
415
 
 
416
 
static DWORD WINAPI thread_main(void *param)
417
 
{
418
 
    pj_thread_t *rec = param;
419
 
    DWORD result;
420
 
 
421
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
422
 
    rec->stk_start = (char*)&rec;
423
 
#endif
424
 
 
425
 
    if (pj_thread_local_set(thread_tls_id, rec) != PJ_SUCCESS) {
426
 
        pj_assert(!"TLS is not set (pj_init() error?)");
427
 
    }
428
 
 
429
 
    PJ_LOG(6,(rec->obj_name, "Thread started"));
430
 
 
431
 
    result = (*rec->proc)(rec->arg);
432
 
 
433
 
    PJ_LOG(6,(rec->obj_name, "Thread quitting"));
434
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
435
 
    PJ_LOG(5,(rec->obj_name, "Thread stack max usage=%u by %s:%d", 
436
 
              rec->stk_max_usage, rec->caller_file, rec->caller_line));
437
 
#endif
438
 
 
439
 
    return (DWORD)result;
440
 
}
441
 
 
442
 
/*
443
 
 * pj_thread_create(...)
444
 
 */
445
 
PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, 
446
 
                                      const char *thread_name,
447
 
                                      pj_thread_proc *proc, 
448
 
                                      void *arg,
449
 
                                      pj_size_t stack_size, 
450
 
                                      unsigned flags,
451
 
                                      pj_thread_t **thread_ptr)
452
 
{
453
 
    DWORD dwflags = 0;
454
 
    pj_thread_t *rec;
455
 
 
456
 
    PJ_CHECK_STACK();
457
 
    PJ_ASSERT_RETURN(pool && proc && thread_ptr, PJ_EINVAL);
458
 
 
459
 
    /* Set flags */
460
 
    if (flags & PJ_THREAD_SUSPENDED)
461
 
        dwflags |= CREATE_SUSPENDED;
462
 
 
463
 
    /* Create thread record and assign name for the thread */
464
 
    rec = (struct pj_thread_t*) pj_pool_calloc(pool, 1, sizeof(pj_thread_t));
465
 
    if (!rec)
466
 
        return PJ_ENOMEM;
467
 
 
468
 
    /* Set name. */
469
 
    if (!thread_name)
470
 
        thread_name = "thr%p";
471
 
 
472
 
    if (strchr(thread_name, '%')) {
473
 
        pj_ansi_snprintf(rec->obj_name, PJ_MAX_OBJ_NAME, thread_name, rec);
474
 
    } else {
475
 
        pj_ansi_strncpy(rec->obj_name, thread_name, PJ_MAX_OBJ_NAME);
476
 
        rec->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
477
 
    }
478
 
 
479
 
    PJ_LOG(6, (rec->obj_name, "Thread created"));
480
 
 
481
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
482
 
    rec->stk_size = stack_size ? stack_size : 0xFFFFFFFFUL;
483
 
    rec->stk_max_usage = 0;
484
 
#endif
485
 
 
486
 
    /* Create the thread. */
487
 
    rec->proc = proc;
488
 
    rec->arg = arg;
489
 
    rec->hthread = CreateThread(NULL, stack_size, 
490
 
                                thread_main, rec,
491
 
                                dwflags, &rec->idthread);
492
 
    if (rec->hthread == NULL)
493
 
        return PJ_RETURN_OS_ERROR(GetLastError());
494
 
 
495
 
    /* Success! */
496
 
    *thread_ptr = rec;
497
 
    return PJ_SUCCESS;
498
 
}
499
 
 
500
 
/*
501
 
 * pj_thread-get_name()
502
 
 */
503
 
PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *p)
504
 
{
505
 
    pj_thread_t *rec = (pj_thread_t*)p;
506
 
 
507
 
    PJ_CHECK_STACK();
508
 
    PJ_ASSERT_RETURN(p, "");
509
 
 
510
 
    return rec->obj_name;
511
 
}
512
 
 
513
 
/*
514
 
 * pj_thread_resume()
515
 
 */
516
 
PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *p)
517
 
{
518
 
    pj_thread_t *rec = (pj_thread_t*)p;
519
 
 
520
 
    PJ_CHECK_STACK();
521
 
    PJ_ASSERT_RETURN(p, PJ_EINVAL);
522
 
 
523
 
    if (ResumeThread(rec->hthread) == (DWORD)-1)
524
 
        return PJ_RETURN_OS_ERROR(GetLastError());
525
 
    else
526
 
        return PJ_SUCCESS;
527
 
}
528
 
 
529
 
/*
530
 
 * pj_thread_this()
531
 
 */
532
 
PJ_DEF(pj_thread_t*) pj_thread_this(void)
533
 
{
534
 
    pj_thread_t *rec = pj_thread_local_get(thread_tls_id);
535
 
 
536
 
    if (rec == NULL) {
537
 
        pj_assert(!"Calling pjlib from unknown/external thread. You must "
538
 
                   "register external threads with pj_thread_register() "
539
 
                   "before calling any pjlib functions.");
540
 
    }
541
 
 
542
 
    /*
543
 
     * MUST NOT check stack because this function is called
544
 
     * by PJ_CHECK_STACK() itself!!!
545
 
     *
546
 
     */
547
 
 
548
 
    return rec;
549
 
}
550
 
 
551
 
/*
552
 
 * pj_thread_join()
553
 
 */
554
 
PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p)
555
 
{
556
 
    pj_thread_t *rec = (pj_thread_t *)p;
557
 
    DWORD rc;
558
 
 
559
 
    PJ_CHECK_STACK();
560
 
    PJ_ASSERT_RETURN(p, PJ_EINVAL);
561
 
 
562
 
    PJ_LOG(6, (pj_thread_this()->obj_name, "Joining thread %s", p->obj_name));
563
 
 
564
 
    rc = WaitForSingleObject(rec->hthread, INFINITE);
565
 
 
566
 
    if (rc==WAIT_OBJECT_0)
567
 
        return PJ_SUCCESS;
568
 
    else if (rc==WAIT_TIMEOUT)
569
 
        return PJ_ETIMEDOUT;
570
 
    else
571
 
        return PJ_RETURN_OS_ERROR(GetLastError());
572
 
}
573
 
 
574
 
/*
575
 
 * pj_thread_destroy()
576
 
 */
577
 
PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *p)
578
 
{
579
 
    pj_thread_t *rec = (pj_thread_t *)p;
580
 
 
581
 
    PJ_CHECK_STACK();
582
 
    PJ_ASSERT_RETURN(p, PJ_EINVAL);
583
 
 
584
 
    if (CloseHandle(rec->hthread) == TRUE)
585
 
        return PJ_SUCCESS;
586
 
    else
587
 
        return PJ_RETURN_OS_ERROR(GetLastError());
588
 
}
589
 
 
590
 
/*
591
 
 * pj_thread_sleep()
592
 
 */
593
 
PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
594
 
{
595
 
    PJ_CHECK_STACK();
596
 
    Sleep(msec);
597
 
    return PJ_SUCCESS;
598
 
}
599
 
 
600
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK != 0
601
 
/*
602
 
 * pj_thread_check_stack()
603
 
 * Implementation for PJ_CHECK_STACK()
604
 
 */
605
 
PJ_DEF(void) pj_thread_check_stack(const char *file, int line)
606
 
{
607
 
    char stk_ptr;
608
 
    pj_uint32_t usage;
609
 
    pj_thread_t *thread = pj_thread_this();
610
 
 
611
 
    pj_assert(thread);
612
 
 
613
 
    /* Calculate current usage. */
614
 
    usage = (&stk_ptr > thread->stk_start) ? &stk_ptr - thread->stk_start :
615
 
                thread->stk_start - &stk_ptr;
616
 
 
617
 
    /* Assert if stack usage is dangerously high. */
618
 
    pj_assert("STACK OVERFLOW!! " && (usage <= thread->stk_size - 128));
619
 
 
620
 
    /* Keep statistic. */
621
 
    if (usage > thread->stk_max_usage) {
622
 
        thread->stk_max_usage = usage;
623
 
        thread->caller_file = file;
624
 
        thread->caller_line = line;
625
 
    }
626
 
 
627
 
}
628
 
 
629
 
/*
630
 
 * pj_thread_get_stack_max_usage()
631
 
 */
632
 
PJ_DEF(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread)
633
 
{
634
 
    return thread->stk_max_usage;
635
 
}
636
 
 
637
 
/*
638
 
 * pj_thread_get_stack_info()
639
 
 */
640
 
PJ_DEF(pj_status_t) pj_thread_get_stack_info( pj_thread_t *thread,
641
 
                                              const char **file,
642
 
                                              int *line )
643
 
{
644
 
    pj_assert(thread);
645
 
 
646
 
    *file = thread->caller_file;
647
 
    *line = thread->caller_line;
648
 
    return 0;
649
 
}
650
 
 
651
 
#endif  /* PJ_OS_HAS_CHECK_STACK */
652
 
 
653
 
 
654
 
///////////////////////////////////////////////////////////////////////////////
655
 
 
656
 
/*
657
 
 * pj_atomic_create()
658
 
 */
659
 
PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool, 
660
 
                                      pj_atomic_value_t initial,
661
 
                                      pj_atomic_t **atomic_ptr)
662
 
{
663
 
    pj_atomic_t *atomic_var = pj_pool_alloc(pool, sizeof(pj_atomic_t));
664
 
    if (!atomic_var)
665
 
        return PJ_ENOMEM;
666
 
 
667
 
    atomic_var->value = initial;
668
 
    *atomic_ptr = atomic_var;
669
 
 
670
 
    return PJ_SUCCESS;
671
 
}
672
 
 
673
 
/*
674
 
 * pj_atomic_destroy()
675
 
 */
676
 
PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *var )
677
 
{
678
 
    PJ_UNUSED_ARG(var);
679
 
    PJ_ASSERT_RETURN(var, PJ_EINVAL);
680
 
 
681
 
    return 0;
682
 
}
683
 
 
684
 
/*
685
 
 * pj_atomic_set()
686
 
 */
687
 
PJ_DEF(void) pj_atomic_set( pj_atomic_t *atomic_var, pj_atomic_value_t value)
688
 
{
689
 
    PJ_CHECK_STACK();
690
 
 
691
 
    InterlockedExchange(&atomic_var->value, value);
692
 
}
693
 
 
694
 
/*
695
 
 * pj_atomic_get()
696
 
 */
697
 
PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
698
 
{
699
 
    PJ_CHECK_STACK();
700
 
    PJ_ASSERT_RETURN(atomic_var, 0);
701
 
 
702
 
    return atomic_var->value;
703
 
}
704
 
 
705
 
/*
706
 
 * pj_atomic_inc_and_get()
707
 
 */
708
 
PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)
709
 
{
710
 
    PJ_CHECK_STACK();
711
 
 
712
 
#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
713
 
    return InterlockedIncrement(&atomic_var->value);
714
 
#else
715
 
    return InterlockedIncrement(&atomic_var->value);
716
 
#endif
717
 
}
718
 
 
719
 
/*
720
 
 * pj_atomic_inc()
721
 
 */
722
 
PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
723
 
{
724
 
    pj_atomic_inc_and_get(atomic_var);
725
 
}
726
 
 
727
 
/*
728
 
 * pj_atomic_dec_and_get()
729
 
 */
730
 
PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
731
 
{
732
 
    PJ_CHECK_STACK();
733
 
 
734
 
#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
735
 
    return InterlockedDecrement(&atomic_var->value);
736
 
#else
737
 
    return InterlockedDecrement(&atomic_var->value);
738
 
#endif
739
 
}
740
 
 
741
 
/*
742
 
 * pj_atomic_dec()
743
 
 */
744
 
PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
745
 
{
746
 
    pj_atomic_dec_and_get(atomic_var);
747
 
}
748
 
 
749
 
/*
750
 
 * pj_atomic_add()
751
 
 */
752
 
PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
753
 
                            pj_atomic_value_t value )
754
 
{
755
 
#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
756
 
    InterlockedExchangeAdd( &atomic_var->value, value );
757
 
#else
758
 
    InterlockedExchangeAdd( &atomic_var->value, value );
759
 
#endif
760
 
}
761
 
 
762
 
/*
763
 
 * pj_atomic_add_and_get()
764
 
 */
765
 
PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
766
 
                                                 pj_atomic_value_t value)
767
 
{
768
 
#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
769
 
    long oldValue = InterlockedExchangeAdd( &atomic_var->value, value);
770
 
    return oldValue + value;
771
 
#else
772
 
    long oldValue = InterlockedExchangeAdd( &atomic_var->value, value);
773
 
    return oldValue + value;
774
 
#endif
775
 
}
776
 
 
777
 
///////////////////////////////////////////////////////////////////////////////
778
 
/*
779
 
 * pj_thread_local_alloc()
780
 
 */
781
 
PJ_DEF(pj_status_t) pj_thread_local_alloc(long *index)
782
 
{
783
 
    PJ_ASSERT_RETURN(index != NULL, PJ_EINVAL);
784
 
 
785
 
    //Can't check stack because this function is called in the
786
 
    //beginning before main thread is initialized.
787
 
    //PJ_CHECK_STACK();
788
 
 
789
 
    *index = TlsAlloc();
790
 
 
791
 
    if (*index == TLS_OUT_OF_INDEXES)
792
 
        return PJ_RETURN_OS_ERROR(GetLastError());
793
 
    else
794
 
        return PJ_SUCCESS;
795
 
}
796
 
 
797
 
/*
798
 
 * pj_thread_local_free()
799
 
 */
800
 
PJ_DEF(void) pj_thread_local_free(long index)
801
 
{
802
 
    PJ_CHECK_STACK();
803
 
    TlsFree(index);
804
 
}
805
 
 
806
 
/*
807
 
 * pj_thread_local_set()
808
 
 */
809
 
PJ_DEF(pj_status_t) pj_thread_local_set(long index, void *value)
810
 
{
811
 
    BOOL rc;
812
 
 
813
 
    //Can't check stack because this function is called in the
814
 
    //beginning before main thread is initialized.
815
 
    //PJ_CHECK_STACK();
816
 
    rc = TlsSetValue(index, value);
817
 
    return rc!=0 ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(GetLastError());
818
 
}
819
 
 
820
 
/*
821
 
 * pj_thread_local_get()
822
 
 */
823
 
PJ_DEF(void*) pj_thread_local_get(long index)
824
 
{
825
 
    //Can't check stack because this function is called
826
 
    //by PJ_CHECK_STACK() itself!!!
827
 
    //PJ_CHECK_STACK();
828
 
    return TlsGetValue(index);
829
 
}
830
 
 
831
 
///////////////////////////////////////////////////////////////////////////////
832
 
static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name)
833
 
{
834
 
 
835
 
    PJ_CHECK_STACK();
836
 
 
837
 
#if PJ_WIN32_WINNT >= 0x0400
838
 
    InitializeCriticalSection(&mutex->crit);
839
 
#else
840
 
    mutex->hMutex = CreateMutex(NULL, FALSE, NULL);
841
 
    if (!mutex->hMutex) {
842
 
        return PJ_RETURN_OS_ERROR(GetLastError());
843
 
    }
844
 
#endif
845
 
 
846
 
#if PJ_DEBUG
847
 
    /* Set owner. */
848
 
    mutex->nesting_level = 0;
849
 
    mutex->owner = NULL;
850
 
#endif
851
 
 
852
 
    /* Set name. */
853
 
    if (!name) {
854
 
        name = "mtx%p";
855
 
    }
856
 
    if (strchr(name, '%')) {
857
 
        pj_ansi_snprintf(mutex->obj_name, PJ_MAX_OBJ_NAME, name, mutex);
858
 
    } else {
859
 
        pj_ansi_strncpy(mutex->obj_name, name, PJ_MAX_OBJ_NAME);
860
 
        mutex->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
861
 
    }
862
 
 
863
 
    PJ_LOG(6, (mutex->obj_name, "Mutex created"));
864
 
    return PJ_SUCCESS;
865
 
}
866
 
 
867
 
/*
868
 
 * pj_mutex_create()
869
 
 */
870
 
PJ_DEF(pj_status_t) pj_mutex_create(pj_pool_t *pool, 
871
 
                                    const char *name, 
872
 
                                    int type,
873
 
                                    pj_mutex_t **mutex_ptr)
874
 
{
875
 
    pj_status_t rc;
876
 
    pj_mutex_t *mutex;
877
 
 
878
 
    PJ_UNUSED_ARG(type);
879
 
    PJ_ASSERT_RETURN(pool && mutex_ptr, PJ_EINVAL);
880
 
 
881
 
    mutex = pj_pool_alloc(pool, sizeof(*mutex));
882
 
    if (!mutex)
883
 
        return PJ_ENOMEM;
884
 
 
885
 
    rc = init_mutex(mutex, name);
886
 
    if (rc != PJ_SUCCESS)
887
 
        return rc;
888
 
 
889
 
    *mutex_ptr = mutex;
890
 
 
891
 
    return PJ_SUCCESS;
892
 
}
893
 
 
894
 
/*
895
 
 * pj_mutex_create_simple()
896
 
 */
897
 
PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, 
898
 
                                            const char *name,
899
 
                                            pj_mutex_t **mutex )
900
 
{
901
 
    return pj_mutex_create(pool, name, PJ_MUTEX_SIMPLE, mutex);
902
 
}
903
 
 
904
 
/*
905
 
 * pj_mutex_create_recursive()
906
 
 */
907
 
PJ_DEF(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
908
 
                                               const char *name,
909
 
                                               pj_mutex_t **mutex )
910
 
{
911
 
    return pj_mutex_create(pool, name, PJ_MUTEX_RECURSE, mutex);
912
 
}
913
 
 
914
 
/*
915
 
 * pj_mutex_lock()
916
 
 */
917
 
PJ_DEF(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex)
918
 
{
919
 
    pj_status_t status;
920
 
 
921
 
    PJ_CHECK_STACK();
922
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
923
 
 
924
 
    LOG_MUTEX((mutex->obj_name, "Mutex: thread %s is waiting", 
925
 
                                pj_thread_this()->obj_name));
926
 
 
927
 
#if PJ_WIN32_WINNT >= 0x0400
928
 
    EnterCriticalSection(&mutex->crit);
929
 
    status=PJ_SUCCESS;
930
 
#else
931
 
    if (WaitForSingleObject(mutex->hMutex, INFINITE)==WAIT_OBJECT_0)
932
 
        status = PJ_SUCCESS;
933
 
    else
934
 
        status = PJ_STATUS_FROM_OS(GetLastError());
935
 
 
936
 
#endif
937
 
    LOG_MUTEX((mutex->obj_name, 
938
 
              (status==PJ_SUCCESS ? "Mutex acquired by thread %s" : "FAILED by %s"),
939
 
              pj_thread_this()->obj_name));
940
 
 
941
 
#if PJ_DEBUG
942
 
    if (status == PJ_SUCCESS) {
943
 
        mutex->owner = pj_thread_this();
944
 
        ++mutex->nesting_level;
945
 
    }
946
 
#endif
947
 
 
948
 
    return status;
949
 
}
950
 
 
951
 
/*
952
 
 * pj_mutex_unlock()
953
 
 */
954
 
PJ_DEF(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex)
955
 
{
956
 
    pj_status_t status;
957
 
 
958
 
    PJ_CHECK_STACK();
959
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
960
 
 
961
 
#if PJ_DEBUG
962
 
    pj_assert(mutex->owner == pj_thread_this());
963
 
    if (--mutex->nesting_level == 0) {
964
 
        mutex->owner = NULL;
965
 
    }
966
 
#endif
967
 
 
968
 
    LOG_MUTEX((mutex->obj_name, "Mutex released by thread %s", 
969
 
                                pj_thread_this()->obj_name));
970
 
 
971
 
#if PJ_WIN32_WINNT >= 0x0400
972
 
    LeaveCriticalSection(&mutex->crit);
973
 
    status=PJ_SUCCESS;
974
 
#else
975
 
    status = ReleaseMutex(mutex->hMutex) ? PJ_SUCCESS : 
976
 
                PJ_STATUS_FROM_OS(GetLastError());
977
 
#endif
978
 
    return status;
979
 
}
980
 
 
981
 
/*
982
 
 * pj_mutex_trylock()
983
 
 */
984
 
PJ_DEF(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex)
985
 
{
986
 
    pj_status_t status;
987
 
 
988
 
    PJ_CHECK_STACK();
989
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
990
 
 
991
 
    LOG_MUTEX((mutex->obj_name, "Mutex: thread %s is trying", 
992
 
                                pj_thread_this()->obj_name));
993
 
 
994
 
#if PJ_WIN32_WINNT >= 0x0400
995
 
    status=TryEnterCriticalSection(&mutex->crit) ? PJ_SUCCESS : PJ_EUNKNOWN;
996
 
#else
997
 
    status = WaitForSingleObject(mutex->hMutex, 0)==WAIT_OBJECT_0 ? 
998
 
                PJ_SUCCESS : PJ_ETIMEDOUT;
999
 
#endif
1000
 
    if (status==PJ_SUCCESS) {
1001
 
        LOG_MUTEX((mutex->obj_name, "Mutex acquired by thread %s", 
1002
 
                                  pj_thread_this()->obj_name));
1003
 
 
1004
 
#if PJ_DEBUG
1005
 
        mutex->owner = pj_thread_this();
1006
 
        ++mutex->nesting_level;
1007
 
#endif
1008
 
    } else {
1009
 
        LOG_MUTEX((mutex->obj_name, "Mutex: thread %s's trylock() failed", 
1010
 
                                    pj_thread_this()->obj_name));
1011
 
    }
1012
 
 
1013
 
    return status;
1014
 
}
1015
 
 
1016
 
/*
1017
 
 * pj_mutex_destroy()
1018
 
 */
1019
 
PJ_DEF(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex)
1020
 
{
1021
 
    PJ_CHECK_STACK();
1022
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
1023
 
 
1024
 
    LOG_MUTEX((mutex->obj_name, "Mutex destroyed"));
1025
 
 
1026
 
#if PJ_WIN32_WINNT >= 0x0400
1027
 
    DeleteCriticalSection(&mutex->crit);
1028
 
    return PJ_SUCCESS;
1029
 
#else
1030
 
    return CloseHandle(mutex->hMutex) ? PJ_SUCCESS : 
1031
 
            PJ_RETURN_OS_ERROR(GetLastError());
1032
 
#endif
1033
 
}
1034
 
 
1035
 
/*
1036
 
 * pj_mutex_is_locked()
1037
 
 */
1038
 
PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex)
1039
 
{
1040
 
#if PJ_DEBUG
1041
 
    return mutex->owner == pj_thread_this();
1042
 
#else
1043
 
    PJ_UNUSED_ARG(mutex);
1044
 
    pj_assert(!"PJ_DEBUG is not set!");
1045
 
    return 1;
1046
 
#endif
1047
 
}
1048
 
 
1049
 
///////////////////////////////////////////////////////////////////////////////
1050
 
/*
1051
 
 * Win32 lacks Read/Write mutex, so include the emulation.
1052
 
 */
1053
 
#include "os_rwmutex.c"
1054
 
 
1055
 
///////////////////////////////////////////////////////////////////////////////
1056
 
/*
1057
 
 * pj_enter_critical_section()
1058
 
 */
1059
 
PJ_DEF(void) pj_enter_critical_section(void)
1060
 
{
1061
 
    pj_mutex_lock(&critical_section_mutex);
1062
 
}
1063
 
 
1064
 
 
1065
 
/*
1066
 
 * pj_leave_critical_section()
1067
 
 */
1068
 
PJ_DEF(void) pj_leave_critical_section(void)
1069
 
{
1070
 
    pj_mutex_unlock(&critical_section_mutex);
1071
 
}
1072
 
 
1073
 
///////////////////////////////////////////////////////////////////////////////
1074
 
#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
1075
 
 
1076
 
/*
1077
 
 * pj_sem_create()
1078
 
 */
1079
 
PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool, 
1080
 
                                   const char *name,
1081
 
                                   unsigned initial, 
1082
 
                                   unsigned max,
1083
 
                                   pj_sem_t **sem_ptr)
1084
 
{
1085
 
    pj_sem_t *sem;
1086
 
 
1087
 
    PJ_CHECK_STACK();
1088
 
    PJ_ASSERT_RETURN(pool && sem_ptr, PJ_EINVAL);
1089
 
 
1090
 
    sem = pj_pool_alloc(pool, sizeof(*sem));    
1091
 
    sem->hSemaphore = CreateSemaphore(NULL, initial, max, NULL);
1092
 
    if (!sem->hSemaphore)
1093
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1094
 
 
1095
 
    /* Set name. */
1096
 
    if (!name) {
1097
 
        name = "sem%p";
1098
 
    }
1099
 
    if (strchr(name, '%')) {
1100
 
        pj_ansi_snprintf(sem->obj_name, PJ_MAX_OBJ_NAME, name, sem);
1101
 
    } else {
1102
 
        pj_ansi_strncpy(sem->obj_name, name, PJ_MAX_OBJ_NAME);
1103
 
        sem->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
1104
 
    }
1105
 
 
1106
 
    LOG_MUTEX((sem->obj_name, "Semaphore created"));
1107
 
 
1108
 
    *sem_ptr = sem;
1109
 
    return PJ_SUCCESS;
1110
 
}
1111
 
 
1112
 
static pj_status_t pj_sem_wait_for(pj_sem_t *sem, unsigned timeout)
1113
 
{
1114
 
    DWORD result;
1115
 
 
1116
 
    PJ_CHECK_STACK();
1117
 
    PJ_ASSERT_RETURN(sem, PJ_EINVAL);
1118
 
 
1119
 
    LOG_MUTEX((sem->obj_name, "Semaphore: thread %s is waiting", 
1120
 
                              pj_thread_this()->obj_name));
1121
 
 
1122
 
    result = WaitForSingleObject(sem->hSemaphore, timeout);
1123
 
    if (result == WAIT_OBJECT_0) {
1124
 
        LOG_MUTEX((sem->obj_name, "Semaphore acquired by thread %s", 
1125
 
                                  pj_thread_this()->obj_name));
1126
 
    } else {
1127
 
        LOG_MUTEX((sem->obj_name, "Semaphore: thread %s FAILED to acquire", 
1128
 
                                  pj_thread_this()->obj_name));
1129
 
    }
1130
 
 
1131
 
    if (result==WAIT_OBJECT_0)
1132
 
        return PJ_SUCCESS;
1133
 
    else if (result==WAIT_TIMEOUT)
1134
 
        return PJ_ETIMEDOUT;
1135
 
    else
1136
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1137
 
}
1138
 
 
1139
 
/*
1140
 
 * pj_sem_wait()
1141
 
 */
1142
 
PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
1143
 
{
1144
 
    PJ_CHECK_STACK();
1145
 
    PJ_ASSERT_RETURN(sem, PJ_EINVAL);
1146
 
 
1147
 
    return pj_sem_wait_for(sem, INFINITE);
1148
 
}
1149
 
 
1150
 
/*
1151
 
 * pj_sem_trywait()
1152
 
 */
1153
 
PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
1154
 
{
1155
 
    PJ_CHECK_STACK();
1156
 
    PJ_ASSERT_RETURN(sem, PJ_EINVAL);
1157
 
 
1158
 
    return pj_sem_wait_for(sem, 0);
1159
 
}
1160
 
 
1161
 
/*
1162
 
 * pj_sem_post()
1163
 
 */
1164
 
PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
1165
 
{
1166
 
    PJ_CHECK_STACK();
1167
 
    PJ_ASSERT_RETURN(sem, PJ_EINVAL);
1168
 
 
1169
 
    LOG_MUTEX((sem->obj_name, "Semaphore released by thread %s",
1170
 
                              pj_thread_this()->obj_name));
1171
 
 
1172
 
    if (ReleaseSemaphore(sem->hSemaphore, 1, NULL))
1173
 
        return PJ_SUCCESS;
1174
 
    else
1175
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1176
 
}
1177
 
 
1178
 
/*
1179
 
 * pj_sem_destroy()
1180
 
 */
1181
 
PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
1182
 
{
1183
 
    PJ_CHECK_STACK();
1184
 
    PJ_ASSERT_RETURN(sem, PJ_EINVAL);
1185
 
 
1186
 
    LOG_MUTEX((sem->obj_name, "Semaphore destroyed by thread %s",
1187
 
                              pj_thread_this()->obj_name));
1188
 
 
1189
 
    if (CloseHandle(sem->hSemaphore))
1190
 
        return PJ_SUCCESS;
1191
 
    else
1192
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1193
 
}
1194
 
 
1195
 
#endif  /* PJ_HAS_SEMAPHORE */
1196
 
///////////////////////////////////////////////////////////////////////////////
1197
 
 
1198
 
 
1199
 
#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
1200
 
 
1201
 
/*
1202
 
 * pj_event_create()
1203
 
 */
1204
 
PJ_DEF(pj_status_t) pj_event_create( pj_pool_t *pool, 
1205
 
                                     const char *name,
1206
 
                                     pj_bool_t manual_reset, 
1207
 
                                     pj_bool_t initial,
1208
 
                                     pj_event_t **event_ptr)
1209
 
{
1210
 
    pj_event_t *event;
1211
 
 
1212
 
    PJ_CHECK_STACK();
1213
 
    PJ_ASSERT_RETURN(pool && event_ptr, PJ_EINVAL);
1214
 
 
1215
 
    event = pj_pool_alloc(pool, sizeof(*event));
1216
 
    if (!event)
1217
 
        return PJ_ENOMEM;
1218
 
 
1219
 
    event->hEvent = CreateEvent(NULL, manual_reset?TRUE:FALSE, 
1220
 
                                initial?TRUE:FALSE, NULL);
1221
 
 
1222
 
    if (!event->hEvent)
1223
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1224
 
 
1225
 
    /* Set name. */
1226
 
    if (!name) {
1227
 
        name = "evt%p";
1228
 
    }
1229
 
    if (strchr(name, '%')) {
1230
 
        pj_ansi_snprintf(event->obj_name, PJ_MAX_OBJ_NAME, name, event);
1231
 
    } else {
1232
 
        pj_ansi_strncpy(event->obj_name, name, PJ_MAX_OBJ_NAME);
1233
 
        event->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
1234
 
    }
1235
 
 
1236
 
    PJ_LOG(6, (event->obj_name, "Event created"));
1237
 
 
1238
 
    *event_ptr = event;
1239
 
    return PJ_SUCCESS;
1240
 
}
1241
 
 
1242
 
static pj_status_t pj_event_wait_for(pj_event_t *event, unsigned timeout)
1243
 
{
1244
 
    DWORD result;
1245
 
 
1246
 
    PJ_CHECK_STACK();
1247
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1248
 
 
1249
 
    PJ_LOG(6, (event->obj_name, "Event: thread %s is waiting", 
1250
 
                                pj_thread_this()->obj_name));
1251
 
 
1252
 
    result = WaitForSingleObject(event->hEvent, timeout);
1253
 
    if (result == WAIT_OBJECT_0) {
1254
 
        PJ_LOG(6, (event->obj_name, "Event: thread %s is released", 
1255
 
                                    pj_thread_this()->obj_name));
1256
 
    } else {
1257
 
        PJ_LOG(6, (event->obj_name, "Event: thread %s FAILED to acquire", 
1258
 
                                    pj_thread_this()->obj_name));
1259
 
    }
1260
 
 
1261
 
    if (result==WAIT_OBJECT_0)
1262
 
        return PJ_SUCCESS;
1263
 
    else if (result==WAIT_TIMEOUT)
1264
 
        return PJ_ETIMEDOUT;
1265
 
    else
1266
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1267
 
}
1268
 
 
1269
 
/*
1270
 
 * pj_event_wait()
1271
 
 */
1272
 
PJ_DEF(pj_status_t) pj_event_wait(pj_event_t *event)
1273
 
{
1274
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1275
 
 
1276
 
    return pj_event_wait_for(event, INFINITE);
1277
 
}
1278
 
 
1279
 
/*
1280
 
 * pj_event_trywait()
1281
 
 */
1282
 
PJ_DEF(pj_status_t) pj_event_trywait(pj_event_t *event)
1283
 
{
1284
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1285
 
 
1286
 
    return pj_event_wait_for(event, 0);
1287
 
}
1288
 
 
1289
 
/*
1290
 
 * pj_event_set()
1291
 
 */
1292
 
PJ_DEF(pj_status_t) pj_event_set(pj_event_t *event)
1293
 
{
1294
 
    PJ_CHECK_STACK();
1295
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1296
 
 
1297
 
    PJ_LOG(6, (event->obj_name, "Setting event"));
1298
 
 
1299
 
    if (SetEvent(event->hEvent))
1300
 
        return PJ_SUCCESS;
1301
 
    else
1302
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1303
 
}
1304
 
 
1305
 
/*
1306
 
 * pj_event_pulse()
1307
 
 */
1308
 
PJ_DEF(pj_status_t) pj_event_pulse(pj_event_t *event)
1309
 
{
1310
 
    PJ_CHECK_STACK();
1311
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1312
 
 
1313
 
    PJ_LOG(6, (event->obj_name, "Pulsing event"));
1314
 
 
1315
 
    if (PulseEvent(event->hEvent))
1316
 
        return PJ_SUCCESS;
1317
 
    else
1318
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1319
 
}
1320
 
 
1321
 
/*
1322
 
 * pj_event_reset()
1323
 
 */
1324
 
PJ_DEF(pj_status_t) pj_event_reset(pj_event_t *event)
1325
 
{
1326
 
    PJ_CHECK_STACK();
1327
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1328
 
 
1329
 
    PJ_LOG(6, (event->obj_name, "Event is reset"));
1330
 
 
1331
 
    if (ResetEvent(event->hEvent))
1332
 
        return PJ_SUCCESS;
1333
 
    else
1334
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1335
 
}
1336
 
 
1337
 
/*
1338
 
 * pj_event_destroy()
1339
 
 */
1340
 
PJ_DEF(pj_status_t) pj_event_destroy(pj_event_t *event)
1341
 
{
1342
 
    PJ_CHECK_STACK();
1343
 
    PJ_ASSERT_RETURN(event, PJ_EINVAL);
1344
 
 
1345
 
    PJ_LOG(6, (event->obj_name, "Event is destroying"));
1346
 
 
1347
 
    if (CloseHandle(event->hEvent))
1348
 
        return PJ_SUCCESS;
1349
 
    else
1350
 
        return PJ_RETURN_OS_ERROR(GetLastError());
1351
 
}
1352
 
 
1353
 
#endif  /* PJ_HAS_EVENT_OBJ */
1354
 
 
1355
 
///////////////////////////////////////////////////////////////////////////////
1356
 
#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0
1357
 
/*
1358
 
 * Terminal color
1359
 
 */
1360
 
 
1361
 
static WORD pj_color_to_os_attr(pj_color_t color)
1362
 
{
1363
 
    WORD attr = 0;
1364
 
 
1365
 
    if (color & PJ_TERM_COLOR_R)
1366
 
        attr |= FOREGROUND_RED;
1367
 
    if (color & PJ_TERM_COLOR_G)
1368
 
        attr |= FOREGROUND_GREEN;
1369
 
    if (color & PJ_TERM_COLOR_B)
1370
 
        attr |= FOREGROUND_BLUE;
1371
 
    if (color & PJ_TERM_COLOR_BRIGHT)
1372
 
        attr |= FOREGROUND_INTENSITY;
1373
 
 
1374
 
    return attr;
1375
 
}
1376
 
 
1377
 
static pj_color_t os_attr_to_pj_color(WORD attr)
1378
 
{
1379
 
    int color = 0;
1380
 
 
1381
 
    if (attr & FOREGROUND_RED)
1382
 
        color |= PJ_TERM_COLOR_R;
1383
 
    if (attr & FOREGROUND_GREEN)
1384
 
        color |= PJ_TERM_COLOR_G;
1385
 
    if (attr & FOREGROUND_BLUE)
1386
 
        color |= PJ_TERM_COLOR_B;
1387
 
    if (attr & FOREGROUND_INTENSITY)
1388
 
        color |= PJ_TERM_COLOR_BRIGHT;
1389
 
 
1390
 
    return color;
1391
 
}
1392
 
 
1393
 
 
1394
 
/*
1395
 
 * pj_term_set_color()
1396
 
 */
1397
 
PJ_DEF(pj_status_t) pj_term_set_color(pj_color_t color)
1398
 
{
1399
 
    BOOL rc;
1400
 
    WORD attr = 0;
1401
 
 
1402
 
    PJ_CHECK_STACK();
1403
 
 
1404
 
    attr = pj_color_to_os_attr(color);
1405
 
    rc = SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), attr);
1406
 
    return rc ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(GetLastError());
1407
 
}
1408
 
 
1409
 
/*
1410
 
 * pj_term_get_color()
1411
 
 * Get current terminal foreground color.
1412
 
 */
1413
 
PJ_DEF(pj_color_t) pj_term_get_color(void)
1414
 
{
1415
 
    CONSOLE_SCREEN_BUFFER_INFO info;
1416
 
 
1417
 
    PJ_CHECK_STACK();
1418
 
 
1419
 
    GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &info);
1420
 
    return os_attr_to_pj_color(info.wAttributes);
1421
 
}
1422
 
 
1423
 
#endif  /* PJ_TERM_HAS_COLOR */