~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): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

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
}