~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

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