~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_linux_kernel.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_linux_kernel.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/assert.h>
22
 
#include <pj/pool.h>
23
 
#include <pj/log.h>
24
 
#include <pj/except.h>
25
 
#include <pj/errno.h>
26
 
#include <pj/string.h>
27
 
#include <pj/compat/high_precision.h>
28
 
#include <pj/compat/sprintf.h>
29
 
 
30
 
#include <linux/config.h>
31
 
#include <linux/version.h>
32
 
#if defined(MODVERSIONS)
33
 
#include <linux/modversions.h>
34
 
#endif
35
 
#include <linux/kernel.h>
36
 
#include <linux/sched.h>
37
 
//#include <linux/tqueue.h>
38
 
#include <linux/wait.h>
39
 
#include <linux/signal.h>
40
 
 
41
 
#include <asm/atomic.h>
42
 
#include <asm/unistd.h>
43
 
#include <asm/semaphore.h>
44
 
 
45
 
#define THIS_FILE   "oslinuxkern"
46
 
 
47
 
struct pj_thread_t
48
 
{
49
 
    /** Thread's name. */
50
 
    char obj_name[PJ_MAX_OBJ_NAME];
51
 
 
52
 
    /** Linux task structure for thread. */
53
 
    struct task_struct *thread; 
54
 
 
55
 
    /** Flags (specified in pj_thread_create) */
56
 
    unsigned flags;
57
 
 
58
 
    /** Task queue needed to launch thread. */
59
 
    //struct tq_struct  tq;     
60
 
 
61
 
    /** Semaphore needed to control thread startup. */
62
 
    struct semaphore    startstop_sem;
63
 
 
64
 
    /** Semaphore to suspend thread during startup. */
65
 
    struct semaphore    suspend_sem;
66
 
 
67
 
    /** Queue thread is waiting on. Gets initialized by
68
 
        thread_initialize, can be used by thread itself.
69
 
     */
70
 
    wait_queue_head_t   queue;
71
 
 
72
 
    /** Flag to tell thread whether to die or not.
73
 
        When the thread receives a signal, it must check
74
 
        the value of terminate and call thread_deinitialize and terminate
75
 
        if set.
76
 
     */
77
 
    int terminate;    
78
 
 
79
 
    /** Thread's entry. */
80
 
    pj_thread_proc *func;
81
 
 
82
 
    /** Argument. */
83
 
    void *arg;
84
 
};
85
 
 
86
 
struct pj_atomic_t
87
 
{
88
 
    atomic_t atom;
89
 
};
90
 
 
91
 
struct pj_mutex_t
92
 
{
93
 
    struct semaphore sem;
94
 
    pj_bool_t        recursive;
95
 
    pj_thread_t     *owner;
96
 
    int              own_count;
97
 
};
98
 
 
99
 
struct pj_sem_t
100
 
{
101
 
    struct semaphore sem;
102
 
};
103
 
 
104
 
/*
105
 
 * Static global variables.
106
 
 */
107
 
#define MAX_TLS_ID  32
108
 
static void *tls_values[MAX_TLS_ID];
109
 
static int tls_id;
110
 
static long thread_tls_id;
111
 
static spinlock_t critical_section = SPIN_LOCK_UNLOCKED;
112
 
static unsigned long spinlock_flags;
113
 
static pj_thread_t main_thread;
114
 
 
115
 
/* private functions */
116
 
//#define TRACE_(expr)  PJ_LOG(3,expr)
117
 
#define TRACE_(x)
118
 
 
119
 
 
120
 
/* This must be called in the context of the new thread. */
121
 
static void thread_initialize( pj_thread_t *thread )
122
 
{
123
 
    TRACE_((THIS_FILE, "---new thread initializing..."));
124
 
 
125
 
    /* Set TLS */
126
 
    pj_thread_local_set(thread_tls_id, thread);
127
 
 
128
 
    /* fill in thread structure */
129
 
    thread->thread = current;
130
 
    pj_assert(thread->thread != NULL);
131
 
 
132
 
    /* set signal mask to what we want to respond */
133
 
    siginitsetinv(&current->blocked, 
134
 
                  sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
135
 
 
136
 
    /* initialise wait queue */
137
 
    init_waitqueue_head(&thread->queue);
138
 
 
139
 
    /* initialise termination flag */
140
 
    thread->terminate = 0;
141
 
 
142
 
    /* set name of this process (making sure obj_name is null 
143
 
     * terminated first) 
144
 
     */
145
 
    thread->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
146
 
    sprintf(current->comm, thread->obj_name);
147
 
        
148
 
    /* tell the creator that we are ready and let him continue */
149
 
    up(&thread->startstop_sem); 
150
 
}
151
 
 
152
 
/* cleanup of thread. Called by the exiting thread. */
153
 
static void thread_deinitialize(pj_thread_t *thread)
154
 
{
155
 
    /* we are terminating */
156
 
 
157
 
    /* lock the kernel, the exit will unlock it */
158
 
    thread->thread = NULL;
159
 
    mb();
160
 
 
161
 
    /* notify the stop_kthread() routine that we are terminating. */
162
 
    up(&thread->startstop_sem);
163
 
 
164
 
    /* the kernel_thread that called clone() does a do_exit here. */
165
 
 
166
 
    /* there is no race here between execution of the "killer" and 
167
 
       real termination of the thread (race window between up and do_exit), 
168
 
       since both the thread and the "killer" function are running with 
169
 
       the kernel lock held.
170
 
       The kernel lock will be freed after the thread exited, so the code
171
 
       is really not executed anymore as soon as the unload functions gets
172
 
       the kernel lock back.
173
 
       The init process may not have made the cleanup of the process here,
174
 
       but the cleanup can be done safely with the module unloaded.
175
 
    */
176
 
 
177
 
}
178
 
 
179
 
static int thread_proc(void *arg)
180
 
{
181
 
    pj_thread_t *thread = arg;
182
 
 
183
 
    TRACE_((THIS_FILE, "---new thread starting!"));
184
 
 
185
 
    /* Initialize thread. */
186
 
    thread_initialize( thread );
187
 
 
188
 
    /* Wait if created suspended. */
189
 
    if (thread->flags & PJ_THREAD_SUSPENDED) {
190
 
        TRACE_((THIS_FILE, "---new thread suspended..."));
191
 
        down(&thread->suspend_sem);
192
 
    }
193
 
 
194
 
    TRACE_((THIS_FILE, "---new thread running..."));
195
 
 
196
 
    pj_assert(thread->func != NULL);
197
 
 
198
 
    /* Call thread's entry. */
199
 
    (*thread->func)(thread->arg);
200
 
 
201
 
    TRACE_((THIS_FILE, "---thread exiting..."));
202
 
 
203
 
    /* Cleanup thread. */
204
 
    thread_deinitialize(thread);
205
 
 
206
 
    return 0;
207
 
}
208
 
 
209
 
/* The very task entry. */
210
 
static void kthread_launcher(void *arg)
211
 
{
212
 
    TRACE_((THIS_FILE, "...launching thread!..."));
213
 
    kernel_thread(&thread_proc, arg, 0);
214
 
}
215
 
 
216
 
PJ_DEF(pj_status_t) pj_init(void)
217
 
{
218
 
    pj_status_t rc;
219
 
 
220
 
    PJ_LOG(5, ("pj_init", "Initializing PJ Library.."));
221
 
 
222
 
    rc = pj_thread_init();
223
 
    if (rc != PJ_SUCCESS)
224
 
        return rc;
225
 
 
226
 
    /* Initialize exception ID for the pool. 
227
 
     * Must do so after critical section is configured.
228
 
     */
229
 
    rc = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION);
230
 
    if (rc != PJ_SUCCESS)
231
 
        return rc;
232
 
 
233
 
    return PJ_SUCCESS;
234
 
}
235
 
 
236
 
PJ_DEF(pj_uint32_t) pj_getpid(void)
237
 
{
238
 
    return 1;
239
 
}
240
 
 
241
 
PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
242
 
                                         pj_thread_desc desc,
243
 
                                         pj_thread_t **ptr_thread)
244
 
{
245
 
    char stack_ptr;
246
 
    pj_thread_t *thread = (pj_thread_t *)desc;
247
 
    pj_str_t thread_name = pj_str((char*)cstr_thread_name);
248
 
 
249
 
    /* Size sanity check. */
250
 
    if (sizeof(pj_thread_desc) < sizeof(pj_thread_t)) {
251
 
        pj_assert(!"Not enough pj_thread_desc size!");
252
 
        return PJ_EBUG;
253
 
    }
254
 
 
255
 
    /* If a thread descriptor has been registered before, just return it. */
256
 
    if (pj_thread_local_get (thread_tls_id) != 0) {
257
 
        // 2006-02-26 bennylp:
258
 
        //  This wouldn't work in all cases!.
259
 
        //  If thread is created by external module (e.g. sound thread),
260
 
        //  thread may be reused while the pool used for the thread descriptor
261
 
        //  has been deleted by application.
262
 
        //*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);
263
 
        //return PJ_SUCCESS;
264
 
    }
265
 
 
266
 
    /* Initialize and set the thread entry. */
267
 
    pj_bzero(desc, sizeof(struct pj_thread_t));
268
 
 
269
 
    if(cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1)
270
 
        pj_sprintf(thread->obj_name, cstr_thread_name, thread->thread);
271
 
    else
272
 
        pj_snprintf(thread->obj_name, sizeof(thread->obj_name), 
273
 
                    "thr%p", (void*)thread->thread);
274
 
    
275
 
    /* Initialize. */
276
 
    thread_initialize(thread);
277
 
 
278
 
    /* Eat semaphore. */
279
 
    down(&thread->startstop_sem);
280
 
 
281
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
282
 
    thread->stk_start = &stack_ptr;
283
 
    thread->stk_size = 0xFFFFFFFFUL;
284
 
    thread->stk_max_usage = 0;
285
 
#else
286
 
    stack_ptr = '\0';
287
 
#endif
288
 
 
289
 
    *ptr_thread = thread;
290
 
    return PJ_SUCCESS;
291
 
}
292
 
 
293
 
 
294
 
pj_status_t pj_thread_init(void)
295
 
{
296
 
    pj_status_t rc;
297
 
    pj_thread_t *dummy;
298
 
    
299
 
    rc = pj_thread_local_alloc(&thread_tls_id);
300
 
    if (rc != PJ_SUCCESS)
301
 
        return rc;
302
 
 
303
 
    return pj_thread_register("pjlib-main", (long*)&main_thread, &dummy);
304
 
}
305
 
 
306
 
PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, const char *thread_name,
307
 
                                      pj_thread_proc *proc, void *arg,
308
 
                                      pj_size_t stack_size, unsigned flags,
309
 
                                      pj_thread_t **ptr_thread)
310
 
{
311
 
    pj_thread_t *thread;
312
 
 
313
 
    TRACE_((THIS_FILE, "pj_thread_create()"));
314
 
    
315
 
    PJ_ASSERT_RETURN(pool && proc && ptr_thread, PJ_EINVAL);
316
 
 
317
 
    thread = pj_pool_zalloc(pool, sizeof(pj_thread_t));
318
 
    if (!thread)
319
 
        return PJ_ENOMEM;
320
 
 
321
 
    PJ_UNUSED_ARG(stack_size);
322
 
 
323
 
    /* Thread name. */
324
 
    if (!thread_name) 
325
 
        thread_name = "thr%p";
326
 
    
327
 
    if (strchr(thread_name, '%')) {
328
 
        pj_snprintf(thread->obj_name, PJ_MAX_OBJ_NAME, thread_name, thread);
329
 
    } else {
330
 
        strncpy(thread->obj_name, thread_name, PJ_MAX_OBJ_NAME);
331
 
        thread->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
332
 
    }
333
 
    
334
 
    /* Init thread's semaphore. */
335
 
    TRACE_((THIS_FILE, "...init semaphores..."));
336
 
    init_MUTEX_LOCKED(&thread->startstop_sem);
337
 
    init_MUTEX_LOCKED(&thread->suspend_sem);
338
 
 
339
 
    thread->flags = flags;
340
 
 
341
 
    if ((flags & PJ_THREAD_SUSPENDED) == 0) {
342
 
        up(&thread->suspend_sem);
343
 
    }
344
 
 
345
 
    /* Store the functions and argument. */
346
 
    thread->func = proc;
347
 
    thread->arg = arg;
348
 
    
349
 
    /* Save return value. */
350
 
    *ptr_thread = thread;
351
 
    
352
 
    /* Create the new thread by running a task through keventd. */
353
 
 
354
 
#if 0
355
 
    /* Initialize the task queue struct. */
356
 
    thread->tq.sync = 0;
357
 
    INIT_LIST_HEAD(&thread->tq.list);
358
 
    thread->tq.routine = kthread_launcher;
359
 
    thread->tq.data = thread;
360
 
 
361
 
    /* and schedule it for execution. */
362
 
    schedule_task(&thread->tq);
363
 
#endif
364
 
    kthread_launcher(thread);
365
 
 
366
 
    /* Wait until thread has reached the setup_thread routine. */
367
 
    TRACE_((THIS_FILE, "...wait for the new thread..."));
368
 
    down(&thread->startstop_sem);
369
 
 
370
 
    TRACE_((THIS_FILE, "...main thread resumed..."));
371
 
    return PJ_SUCCESS;
372
 
}
373
 
 
374
 
PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *thread)
375
 
{
376
 
    return thread->obj_name;
377
 
}
378
 
 
379
 
PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *thread)
380
 
{
381
 
    up(&thread->suspend_sem);
382
 
    return PJ_SUCCESS;
383
 
}
384
 
 
385
 
PJ_DEF(pj_thread_t*) pj_thread_this(void)
386
 
{
387
 
    return (pj_thread_t*)pj_thread_local_get(thread_tls_id);
388
 
}
389
 
 
390
 
PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p)
391
 
{
392
 
    TRACE_((THIS_FILE, "pj_thread_join()"));
393
 
    down(&p->startstop_sem);
394
 
    TRACE_((THIS_FILE, "  joined!"));
395
 
    return PJ_SUCCESS;
396
 
}
397
 
 
398
 
PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *thread)
399
 
{
400
 
    PJ_ASSERT_RETURN(thread != NULL, PJ_EINVALIDOP);
401
 
    return PJ_SUCCESS;
402
 
}
403
 
 
404
 
PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
405
 
{
406
 
    pj_highprec_t ticks;
407
 
    pj_thread_t *thread = pj_thread_this();
408
 
 
409
 
    PJ_ASSERT_RETURN(thread != NULL, PJ_EBUG);
410
 
    
411
 
    /* Use high precision calculation to make sure we don't
412
 
     * crop values:
413
 
     *
414
 
     *  ticks = HZ * msec / 1000
415
 
     */
416
 
    ticks = HZ;
417
 
    pj_highprec_mul(ticks, msec);
418
 
    pj_highprec_div(ticks, 1000);
419
 
 
420
 
    TRACE_((THIS_FILE, "this thread will sleep for %u ticks", ticks));
421
 
    interruptible_sleep_on_timeout( &thread->queue, ticks);
422
 
    return PJ_SUCCESS;
423
 
}
424
 
 
425
 
 
426
 
///////////////////////////////////////////////////////////////////////////////
427
 
PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool, 
428
 
                                      pj_atomic_value_t value,
429
 
                                      pj_atomic_t **ptr_var)
430
 
{
431
 
    pj_atomic_t *t = pj_pool_calloc(pool, 1, sizeof(pj_atomic_t));
432
 
    if (!t) return PJ_ENOMEM;
433
 
 
434
 
    atomic_set(&t->atom, value);
435
 
    *ptr_var = t;
436
 
    
437
 
    return PJ_SUCCESS;
438
 
}
439
 
 
440
 
PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *var )
441
 
{
442
 
    return PJ_SUCCESS;
443
 
}
444
 
 
445
 
PJ_DEF(void) pj_atomic_set(pj_atomic_t *var, pj_atomic_value_t value)
446
 
{
447
 
    atomic_set(&var->atom, value);
448
 
}
449
 
 
450
 
PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *var)
451
 
{
452
 
    return atomic_read(&var->atom);
453
 
}
454
 
 
455
 
PJ_DEF(void) pj_atomic_inc(pj_atomic_t *var)
456
 
{
457
 
    atomic_inc(&var->atom);
458
 
}
459
 
 
460
 
PJ_DEF(void) pj_atomic_dec(pj_atomic_t *var)
461
 
{
462
 
    atomic_dec(&var->atom);
463
 
}
464
 
 
465
 
PJ_DEF(void) pj_atomic_add( pj_atomic_t *var, pj_atomic_value_t value )
466
 
{
467
 
    atomic_add(value, &var->atom);
468
 
}
469
 
 
470
 
 
471
 
///////////////////////////////////////////////////////////////////////////////
472
 
PJ_DEF(pj_status_t) pj_thread_local_alloc(long *index)
473
 
{
474
 
    if (tls_id >= MAX_TLS_ID)
475
 
        return PJ_ETOOMANY;
476
 
    
477
 
    *index = tls_id++;
478
 
 
479
 
    return PJ_SUCCESS;
480
 
}
481
 
 
482
 
PJ_DEF(void) pj_thread_local_free(long index)
483
 
{
484
 
    pj_assert(index >= 0 && index < MAX_TLS_ID);
485
 
}
486
 
 
487
 
PJ_DEF(pj_status_t) pj_thread_local_set(long index, void *value)
488
 
{
489
 
    pj_assert(index >= 0 && index < MAX_TLS_ID);
490
 
    tls_values[index] = value;
491
 
    return PJ_SUCCESS;
492
 
}
493
 
 
494
 
PJ_DEF(void*) pj_thread_local_get(long index)
495
 
{
496
 
    pj_assert(index >= 0 && index < MAX_TLS_ID);
497
 
    return tls_values[index];
498
 
}
499
 
 
500
 
 
501
 
///////////////////////////////////////////////////////////////////////////////
502
 
PJ_DEF(void) pj_enter_critical_section(void)
503
 
{
504
 
    spin_lock_irqsave(&critical_section, spinlock_flags);
505
 
}
506
 
 
507
 
PJ_DEF(void) pj_leave_critical_section(void)
508
 
{
509
 
    spin_unlock_irqrestore(&critical_section, spinlock_flags);
510
 
}
511
 
 
512
 
 
513
 
///////////////////////////////////////////////////////////////////////////////
514
 
PJ_DEF(pj_status_t) pj_mutex_create( pj_pool_t *pool, 
515
 
                                     const char *name, 
516
 
                                     int type,
517
 
                                     pj_mutex_t **ptr_mutex)
518
 
{
519
 
    pj_mutex_t *mutex;
520
 
    
521
 
    PJ_UNUSED_ARG(name);
522
 
 
523
 
    mutex = pj_pool_alloc(pool, sizeof(pj_mutex_t));
524
 
    if (!mutex)
525
 
        return PJ_ENOMEM;
526
 
 
527
 
    init_MUTEX(&mutex->sem);
528
 
 
529
 
    mutex->recursive = (type == PJ_MUTEX_RECURSE);
530
 
    mutex->owner = NULL;
531
 
    mutex->own_count = 0;
532
 
    
533
 
    /* Done. */
534
 
    *ptr_mutex = mutex;
535
 
    return PJ_SUCCESS;
536
 
}
537
 
 
538
 
PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,
539
 
                                            pj_mutex_t **mutex )
540
 
{
541
 
    return pj_mutex_create(pool, name, PJ_MUTEX_SIMPLE, mutex);
542
 
}
543
 
 
544
 
PJ_DEF(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
545
 
                                               const char *name,
546
 
                                               pj_mutex_t **mutex )
547
 
{
548
 
    return pj_mutex_create( pool, name, PJ_MUTEX_RECURSE, mutex);
549
 
}
550
 
 
551
 
PJ_DEF(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex)
552
 
{
553
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
554
 
 
555
 
    if (mutex->recursive) {
556
 
        pj_thread_t *this_thread = pj_thread_this();
557
 
        if (mutex->owner == this_thread) {
558
 
            ++mutex->own_count;
559
 
        } else {
560
 
            down(&mutex->sem);
561
 
            pj_assert(mutex->own_count == 0);
562
 
            mutex->owner = this_thread;
563
 
            mutex->own_count = 1;
564
 
        }
565
 
    } else {
566
 
        down(&mutex->sem);
567
 
    }
568
 
    return PJ_SUCCESS;
569
 
}
570
 
 
571
 
PJ_DEF(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex)
572
 
{
573
 
    long rc;
574
 
 
575
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
576
 
 
577
 
    if (mutex->recursive) {
578
 
        pj_thread_t *this_thread = pj_thread_this();
579
 
        if (mutex->owner == this_thread) {
580
 
            ++mutex->own_count;
581
 
        } else {
582
 
            rc = down_interruptible(&mutex->sem);
583
 
            if (rc != 0)
584
 
                return PJ_RETURN_OS_ERROR(-rc);
585
 
            pj_assert(mutex->own_count == 0);
586
 
            mutex->owner = this_thread;
587
 
            mutex->own_count = 1;
588
 
        }
589
 
    } else {
590
 
        int rc = down_trylock(&mutex->sem);
591
 
        if (rc != 0)
592
 
            return PJ_RETURN_OS_ERROR(-rc);
593
 
    }
594
 
    return PJ_SUCCESS;
595
 
}
596
 
 
597
 
PJ_DEF(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex)
598
 
{
599
 
    PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
600
 
 
601
 
    if (mutex->recursive) {
602
 
        pj_thread_t *this_thread = pj_thread_this();
603
 
        if (mutex->owner == this_thread) {
604
 
            pj_assert(mutex->own_count > 0);
605
 
            --mutex->own_count;
606
 
            if (mutex->own_count == 0) {
607
 
                mutex->owner = NULL;
608
 
                up(&mutex->sem);
609
 
            }
610
 
        } else {
611
 
            pj_assert(!"Not owner!");
612
 
            return PJ_EINVALIDOP;
613
 
        }
614
 
    } else {
615
 
        up(&mutex->sem);
616
 
    }
617
 
    return PJ_SUCCESS;
618
 
}
619
 
 
620
 
PJ_DEF(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex)
621
 
{
622
 
    PJ_ASSERT_RETURN(mutex != NULL, PJ_EINVAL);
623
 
 
624
 
    return PJ_SUCCESS;
625
 
}
626
 
 
627
 
#if defined(PJ_DEBUG) && PJ_DEBUG != 0
628
 
PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex)
629
 
{
630
 
    if (mutex->recursive)
631
 
        return mutex->owner == pj_thread_this();
632
 
    else
633
 
        return 1;
634
 
}
635
 
#endif  /* PJ_DEBUG */
636
 
 
637
 
 
638
 
#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
639
 
 
640
 
PJ_DEF(pj_status_t) pj_sem_create(  pj_pool_t *pool, 
641
 
                                    const char *name,
642
 
                                    unsigned initial, 
643
 
                                    unsigned max,
644
 
                                    pj_sem_t **sem)
645
 
{
646
 
    pj_sem_t *sem;
647
 
 
648
 
    PJ_UNUSED_ARG(max);
649
 
 
650
 
    PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
651
 
    
652
 
    sem = pj_pool_alloc(pool, sizeof(pj_sem_t));
653
 
    sema_init(&sem->sem, initial);
654
 
    return PJ_SUCCESS;
655
 
}
656
 
 
657
 
PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
658
 
{
659
 
    PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
660
 
 
661
 
    down(&sem->sem);
662
 
    return PJ_SUCCESS;
663
 
}
664
 
 
665
 
PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
666
 
{
667
 
    int rc;
668
 
 
669
 
    PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
670
 
 
671
 
    rc = down_trylock(&sem->sem);
672
 
    if (rc != 0) {
673
 
        return PJ_RETURN_OS_ERROR(-rc);
674
 
    } else {
675
 
        return PJ_SUCCESS;
676
 
    }
677
 
}
678
 
 
679
 
PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
680
 
{
681
 
    PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
682
 
 
683
 
    up(&sem->sem);
684
 
    return PJ_SUCCESS;
685
 
}
686
 
 
687
 
PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
688
 
{
689
 
    PJ_ASSERT_RETURN(pool && sem, PJ_EINVAL);
690
 
 
691
 
    return PJ_SUCCESS;
692
 
}
693
 
 
694
 
#endif  /* PJ_HAS_SEMAPHORE */
695
 
 
696
 
 
697
 
 
698