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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjlib/src/pj/os_core_symbian.cpp

  • 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_symbian.cpp 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
 
 
21
 
#include <pj/os.h>
22
 
#include <pj/assert.h>
23
 
#include <pj/pool.h>
24
 
#include <pj/log.h>
25
 
#include <pj/rand.h>
26
 
#include <pj/string.h>
27
 
#include <pj/guid.h>
28
 
#include <pj/except.h>
29
 
#include <pj/errno.h>
30
 
 
31
 
#include "os_symbian.h"
32
 
 
33
 
 
34
 
#define PJ_MAX_TLS          32
35
 
#define DUMMY_MUTEX         ((pj_mutex_t*)101)
36
 
#define DUMMY_SEMAPHORE     ((pj_sem_t*)102)
37
 
#define THIS_FILE           "os_core_symbian.c"
38
 
 
39
 
/* Default message slot number for RSocketServ::Connect().
40
 
 * Increase it to 32 from the default 8 (KESockDefaultMessageSlots)
41
 
 */
42
 
#ifndef PJ_SYMBIAN_SOCK_MSG_SLOTS
43
 
#  define PJ_SYMBIAN_SOCK_MSG_SLOTS  32
44
 
#endif
45
 
 
46
 
/*
47
 
 * Note:
48
 
 *
49
 
 * The Symbian implementation does not support threading!
50
 
 */
51
 
 
52
 
struct pj_thread_t
53
 
{
54
 
    char            obj_name[PJ_MAX_OBJ_NAME];
55
 
    void           *tls_values[PJ_MAX_TLS];
56
 
 
57
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
58
 
    pj_uint32_t     stk_size;
59
 
    pj_uint32_t     stk_max_usage;
60
 
    char           *stk_start;
61
 
    const char     *caller_file;
62
 
    int             caller_line;
63
 
#endif
64
 
 
65
 
} main_thread;
66
 
 
67
 
struct pj_atomic_t
68
 
{
69
 
    pj_atomic_value_t   value;
70
 
};
71
 
 
72
 
struct pj_sem_t
73
 
{
74
 
    int value;
75
 
    int max;
76
 
};
77
 
 
78
 
/* Flag and reference counter for PJLIB instance */
79
 
static int initialized;
80
 
 
81
 
/* Flags to indicate which TLS variables have been used */
82
 
static int tls_vars[PJ_MAX_TLS];
83
 
 
84
 
/* atexit handlers */
85
 
static unsigned atexit_count;
86
 
static void (*atexit_func[32])(void);
87
 
 
88
 
 
89
 
/////////////////////////////////////////////////////////////////////////////
90
 
//
91
 
// CPjTimeoutTimer implementation
92
 
//
93
 
 
94
 
CPjTimeoutTimer::CPjTimeoutTimer()
95
 
: CActive(PJ_SYMBIAN_TIMER_PRIORITY), hasTimedOut_(PJ_FALSE)
96
 
{
97
 
}
98
 
 
99
 
CPjTimeoutTimer::~CPjTimeoutTimer()
100
 
{
101
 
    Cancel();
102
 
    timer_.Close();
103
 
}
104
 
 
105
 
void CPjTimeoutTimer::ConstructL()
106
 
{
107
 
    hasTimedOut_ = PJ_FALSE;
108
 
    timer_.CreateLocal();
109
 
    CActiveScheduler::Add(this);
110
 
}
111
 
 
112
 
CPjTimeoutTimer *CPjTimeoutTimer::NewL()
113
 
{
114
 
    CPjTimeoutTimer *self = new CPjTimeoutTimer;
115
 
    CleanupStack::PushL(self);
116
 
 
117
 
    self->ConstructL();
118
 
 
119
 
    CleanupStack::Pop(self);
120
 
    return self;
121
 
 
122
 
}
123
 
 
124
 
void CPjTimeoutTimer::StartTimer(TUint miliSeconds)
125
 
{
126
 
    Cancel();
127
 
 
128
 
    hasTimedOut_ = PJ_FALSE;
129
 
    timer_.After(iStatus, miliSeconds * 1000);
130
 
    SetActive();
131
 
}
132
 
 
133
 
bool CPjTimeoutTimer::HasTimedOut() const
134
 
{
135
 
    return hasTimedOut_ != 0;
136
 
}
137
 
 
138
 
void CPjTimeoutTimer::RunL()
139
 
{
140
 
    hasTimedOut_ = PJ_TRUE;
141
 
}
142
 
 
143
 
void CPjTimeoutTimer::DoCancel()
144
 
{
145
 
    timer_.Cancel();
146
 
}
147
 
 
148
 
TInt CPjTimeoutTimer::RunError(TInt aError)
149
 
{
150
 
    PJ_UNUSED_ARG(aError);
151
 
    return KErrNone;
152
 
}
153
 
 
154
 
 
155
 
 
156
 
/////////////////////////////////////////////////////////////////////////////
157
 
//
158
 
// PjSymbianOS implementation
159
 
//
160
 
 
161
 
PjSymbianOS::PjSymbianOS()
162
 
: isConnectionUp_(false),
163
 
  isSocketServInitialized_(false), isResolverInitialized_(false),
164
 
  console_(NULL), selectTimeoutTimer_(NULL),
165
 
  appSocketServ_(NULL), appConnection_(NULL), appHostResolver_(NULL),
166
 
  appHostResolver6_(NULL)
167
 
{
168
 
}
169
 
 
170
 
// Set parameters
171
 
void PjSymbianOS::SetParameters(pj_symbianos_params *params)
172
 
{
173
 
    appSocketServ_ = (RSocketServ*) params->rsocketserv;
174
 
    appConnection_ = (RConnection*) params->rconnection;
175
 
    appHostResolver_ = (RHostResolver*) params->rhostresolver;
176
 
    appHostResolver6_ = (RHostResolver*) params->rhostresolver6;
177
 
}
178
 
 
179
 
// Get PjSymbianOS instance
180
 
PjSymbianOS *PjSymbianOS::Instance()
181
 
{
182
 
    static PjSymbianOS instance_;
183
 
    return &instance_;
184
 
}
185
 
 
186
 
 
187
 
// Initialize
188
 
TInt PjSymbianOS::Initialize()
189
 
{
190
 
    TInt err;
191
 
 
192
 
    selectTimeoutTimer_ = CPjTimeoutTimer::NewL();
193
 
 
194
 
#if 0
195
 
    pj_assert(console_ == NULL);
196
 
    TRAPD(err, console_ = Console::NewL(_L("PJLIB"),
197
 
                                        TSize(KConsFullScreen,KConsFullScreen)));
198
 
    return err;
199
 
#endif
200
 
 
201
 
    /* Only create RSocketServ if application doesn't specify it
202
 
     * in the parameters
203
 
     */
204
 
    if (!isSocketServInitialized_ && appSocketServ_ == NULL) {
205
 
        err = socketServ_.Connect(PJ_SYMBIAN_SOCK_MSG_SLOTS);
206
 
        if (err != KErrNone)
207
 
            goto on_error;
208
 
 
209
 
        isSocketServInitialized_ = true;
210
 
    }
211
 
 
212
 
    if (!isResolverInitialized_) {
213
 
        if (appHostResolver_ == NULL) {
214
 
            if (Connection())
215
 
                err = hostResolver_.Open(SocketServ(), KAfInet, KSockStream,
216
 
                                         *Connection());
217
 
            else
218
 
                err = hostResolver_.Open(SocketServ(), KAfInet, KSockStream);
219
 
 
220
 
            if (err != KErrNone)
221
 
                goto on_error;
222
 
        }
223
 
 
224
 
#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0
225
 
        if (appHostResolver6_ == NULL) {
226
 
            if (Connection())
227
 
                err = hostResolver6_.Open(SocketServ(), KAfInet6, KSockStream,
228
 
                                          *Connection());
229
 
            else
230
 
                err = hostResolver6_.Open(SocketServ(), KAfInet6, KSockStream);
231
 
 
232
 
            if (err != KErrNone)
233
 
                goto on_error;
234
 
        }
235
 
#endif
236
 
 
237
 
 
238
 
        isResolverInitialized_ = true;
239
 
    }
240
 
 
241
 
    isConnectionUp_ = true;
242
 
 
243
 
    return KErrNone;
244
 
 
245
 
on_error:
246
 
    Shutdown();
247
 
    return err;
248
 
}
249
 
 
250
 
// Shutdown
251
 
void PjSymbianOS::Shutdown()
252
 
{
253
 
    isConnectionUp_ = false;
254
 
 
255
 
    if (isResolverInitialized_) {
256
 
                hostResolver_.Close();
257
 
#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0
258
 
        hostResolver6_.Close();
259
 
#endif
260
 
        isResolverInitialized_ = false;
261
 
    }
262
 
 
263
 
    if (isSocketServInitialized_) {
264
 
        socketServ_.Close();
265
 
        isSocketServInitialized_ = false;
266
 
    }
267
 
 
268
 
    delete console_;
269
 
    console_ = NULL;
270
 
 
271
 
    delete selectTimeoutTimer_;
272
 
    selectTimeoutTimer_ = NULL;
273
 
 
274
 
    appSocketServ_ = NULL;
275
 
    appConnection_ = NULL;
276
 
    appHostResolver_ = NULL;
277
 
    appHostResolver6_ = NULL;
278
 
}
279
 
 
280
 
// Convert to Unicode
281
 
TInt PjSymbianOS::ConvertToUnicode(TDes16 &aUnicode, const TDesC8 &aForeign)
282
 
{
283
 
#if 0
284
 
    pj_assert(conv_ != NULL);
285
 
    return conv_->ConvertToUnicode(aUnicode, aForeign, convToUnicodeState_);
286
 
#else
287
 
    return CnvUtfConverter::ConvertToUnicodeFromUtf8(aUnicode, aForeign);
288
 
#endif
289
 
}
290
 
 
291
 
// Convert from Unicode
292
 
TInt PjSymbianOS::ConvertFromUnicode(TDes8 &aForeign, const TDesC16 &aUnicode)
293
 
{
294
 
#if 0
295
 
    pj_assert(conv_ != NULL);
296
 
    return conv_->ConvertFromUnicode(aForeign, aUnicode, convToAnsiState_);
297
 
#else
298
 
    return CnvUtfConverter::ConvertFromUnicodeToUtf8(aForeign, aUnicode);
299
 
#endif
300
 
}
301
 
 
302
 
 
303
 
/////////////////////////////////////////////////////////////////////////////
304
 
//
305
 
// PJLIB os.h implementation
306
 
//
307
 
 
308
 
PJ_DEF(pj_uint32_t) pj_getpid(void)
309
 
{
310
 
    return 0;
311
 
}
312
 
 
313
 
 
314
 
/* Set Symbian specific parameters */
315
 
PJ_DEF(pj_status_t) pj_symbianos_set_params(pj_symbianos_params *prm)
316
 
{
317
 
    PJ_ASSERT_RETURN(prm != NULL, PJ_EINVAL);
318
 
    PjSymbianOS::Instance()->SetParameters(prm);
319
 
    return PJ_SUCCESS;
320
 
}
321
 
 
322
 
 
323
 
/* Set connection status */
324
 
PJ_DEF(void) pj_symbianos_set_connection_status(pj_bool_t up)
325
 
{
326
 
    PjSymbianOS::Instance()->SetConnectionStatus(up != 0);
327
 
}
328
 
 
329
 
 
330
 
/*
331
 
 * pj_init(void).
332
 
 * Init PJLIB!
333
 
 */
334
 
PJ_DEF(pj_status_t) pj_init(void)
335
 
{
336
 
        char stack_ptr;
337
 
    pj_status_t status;
338
 
 
339
 
    /* Check if PJLIB have been initialized */
340
 
    if (initialized) {
341
 
        ++initialized;
342
 
        return PJ_SUCCESS;
343
 
    }
344
 
 
345
 
    pj_ansi_strcpy(main_thread.obj_name, "pjthread");
346
 
 
347
 
    // Init main thread
348
 
    pj_memset(&main_thread, 0, sizeof(main_thread));
349
 
 
350
 
    // Initialize PjSymbianOS instance
351
 
    PjSymbianOS *os = PjSymbianOS::Instance();
352
 
 
353
 
    PJ_LOG(4,(THIS_FILE, "Initializing PJLIB for Symbian OS.."));
354
 
 
355
 
    TInt err;
356
 
    err = os->Initialize();
357
 
    if (err != KErrNone)
358
 
        return PJ_RETURN_OS_ERROR(err);
359
 
 
360
 
    /* Init logging */
361
 
    pj_log_init();
362
 
 
363
 
    /* Initialize exception ID for the pool.
364
 
     * Must do so after critical section is configured.
365
 
     */
366
 
    status = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION);
367
 
    if (status != PJ_SUCCESS)
368
 
        goto on_error;
369
 
 
370
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
371
 
    main_thread.stk_start = &stack_ptr;
372
 
    main_thread.stk_size = 0xFFFFFFFFUL;
373
 
    main_thread.stk_max_usage = 0;
374
 
#else
375
 
    stack_ptr = '\0';
376
 
#endif
377
 
 
378
 
    /* Flag PJLIB as initialized */
379
 
    ++initialized;
380
 
    pj_assert(initialized == 1);
381
 
 
382
 
    PJ_LOG(5,(THIS_FILE, "PJLIB initialized."));
383
 
    return PJ_SUCCESS;
384
 
 
385
 
on_error:
386
 
    pj_shutdown();
387
 
    return PJ_RETURN_OS_ERROR(err);
388
 
}
389
 
 
390
 
 
391
 
PJ_DEF(pj_status_t) pj_atexit(pj_exit_callback func)
392
 
{
393
 
    if (atexit_count >= PJ_ARRAY_SIZE(atexit_func))
394
 
        return PJ_ETOOMANY;
395
 
 
396
 
    atexit_func[atexit_count++] = func;
397
 
    return PJ_SUCCESS;
398
 
}
399
 
 
400
 
 
401
 
 
402
 
PJ_DEF(void) pj_shutdown(void)
403
 
{
404
 
    /* Only perform shutdown operation when 'initialized' reaches zero */
405
 
    pj_assert(initialized > 0);
406
 
    if (--initialized != 0)
407
 
        return;
408
 
 
409
 
    /* Call atexit() functions */
410
 
    while (atexit_count > 0) {
411
 
        (*atexit_func[atexit_count-1])();
412
 
        --atexit_count;
413
 
    }
414
 
 
415
 
    /* Free exception ID */
416
 
    if (PJ_NO_MEMORY_EXCEPTION != -1) {
417
 
        pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION);
418
 
        PJ_NO_MEMORY_EXCEPTION = -1;
419
 
    }
420
 
 
421
 
    /* Clear static variables */
422
 
    pj_errno_clear_handlers();
423
 
 
424
 
    PjSymbianOS *os = PjSymbianOS::Instance();
425
 
    os->Shutdown();
426
 
}
427
 
 
428
 
/////////////////////////////////////////////////////////////////////////////
429
 
 
430
 
class CPollTimeoutTimer : public CActive
431
 
{
432
 
public:
433
 
    static CPollTimeoutTimer* NewL(int msec, TInt prio);
434
 
    ~CPollTimeoutTimer();
435
 
 
436
 
    virtual void RunL();
437
 
    virtual void DoCancel();
438
 
 
439
 
private:
440
 
    RTimer           rtimer_;
441
 
 
442
 
    explicit CPollTimeoutTimer(TInt prio);
443
 
    void ConstructL(int msec);
444
 
};
445
 
 
446
 
CPollTimeoutTimer::CPollTimeoutTimer(TInt prio)
447
 
: CActive(prio)
448
 
{
449
 
}
450
 
 
451
 
 
452
 
CPollTimeoutTimer::~CPollTimeoutTimer()
453
 
{
454
 
    rtimer_.Close();
455
 
}
456
 
 
457
 
void CPollTimeoutTimer::ConstructL(int msec)
458
 
{
459
 
    rtimer_.CreateLocal();
460
 
    CActiveScheduler::Add(this);
461
 
    rtimer_.After(iStatus, msec*1000);
462
 
    SetActive();
463
 
}
464
 
 
465
 
CPollTimeoutTimer* CPollTimeoutTimer::NewL(int msec, TInt prio)
466
 
{
467
 
    CPollTimeoutTimer *self = new CPollTimeoutTimer(prio);
468
 
    CleanupStack::PushL(self);
469
 
    self->ConstructL(msec);
470
 
    CleanupStack::Pop(self);
471
 
 
472
 
    return self;
473
 
}
474
 
 
475
 
void CPollTimeoutTimer::RunL()
476
 
{
477
 
}
478
 
 
479
 
void CPollTimeoutTimer::DoCancel()
480
 
{
481
 
     rtimer_.Cancel();
482
 
}
483
 
 
484
 
 
485
 
/*
486
 
 * Wait the completion of any Symbian active objects.
487
 
 */
488
 
PJ_DEF(pj_bool_t) pj_symbianos_poll(int priority, int ms_timeout)
489
 
{
490
 
    CPollTimeoutTimer *timer = NULL;
491
 
 
492
 
    if (priority==-1)
493
 
        priority = EPriorityNull;
494
 
 
495
 
    if (ms_timeout >= 0) {
496
 
        timer = CPollTimeoutTimer::NewL(ms_timeout, priority);
497
 
    }
498
 
 
499
 
    PjSymbianOS::Instance()->WaitForActiveObjects(priority);
500
 
 
501
 
    if (timer) {
502
 
        bool timer_is_active = timer->IsActive();
503
 
 
504
 
        timer->Cancel();
505
 
 
506
 
        delete timer;
507
 
 
508
 
        return timer_is_active ? PJ_TRUE : PJ_FALSE;
509
 
 
510
 
    } else {
511
 
        return PJ_TRUE;
512
 
    }
513
 
}
514
 
 
515
 
 
516
 
/*
517
 
 * pj_thread_is_registered()
518
 
 */
519
 
PJ_DEF(pj_bool_t) pj_thread_is_registered(void)
520
 
{
521
 
    return PJ_FALSE;
522
 
}
523
 
 
524
 
 
525
 
/*
526
 
 * Get thread priority value for the thread.
527
 
 */
528
 
PJ_DEF(int) pj_thread_get_prio(pj_thread_t *thread)
529
 
{
530
 
    PJ_UNUSED_ARG(thread);
531
 
    return 1;
532
 
}
533
 
 
534
 
 
535
 
/*
536
 
 * Set the thread priority.
537
 
 */
538
 
PJ_DEF(pj_status_t) pj_thread_set_prio(pj_thread_t *thread,  int prio)
539
 
{
540
 
    PJ_UNUSED_ARG(thread);
541
 
    PJ_UNUSED_ARG(prio);
542
 
    return PJ_SUCCESS;
543
 
}
544
 
 
545
 
 
546
 
/*
547
 
 * Get the lowest priority value available on this system.
548
 
 */
549
 
PJ_DEF(int) pj_thread_get_prio_min(pj_thread_t *thread)
550
 
{
551
 
    PJ_UNUSED_ARG(thread);
552
 
    return 1;
553
 
}
554
 
 
555
 
 
556
 
/*
557
 
 * Get the highest priority value available on this system.
558
 
 */
559
 
PJ_DEF(int) pj_thread_get_prio_max(pj_thread_t *thread)
560
 
{
561
 
    PJ_UNUSED_ARG(thread);
562
 
    return 1;
563
 
}
564
 
 
565
 
 
566
 
/*
567
 
 * pj_thread_get_os_handle()
568
 
 */
569
 
PJ_DEF(void*) pj_thread_get_os_handle(pj_thread_t *thread)
570
 
{
571
 
    PJ_UNUSED_ARG(thread);
572
 
    return NULL;
573
 
}
574
 
 
575
 
/*
576
 
 * pj_thread_register(..)
577
 
 */
578
 
PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
579
 
                                         pj_thread_desc desc,
580
 
                                         pj_thread_t **thread_ptr)
581
 
{
582
 
    PJ_UNUSED_ARG(cstr_thread_name);
583
 
    PJ_UNUSED_ARG(desc);
584
 
    PJ_UNUSED_ARG(thread_ptr);
585
 
    return PJ_EINVALIDOP;
586
 
}
587
 
 
588
 
 
589
 
/*
590
 
 * pj_thread_create(...)
591
 
 */
592
 
PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool,
593
 
                                      const char *thread_name,
594
 
                                      pj_thread_proc *proc,
595
 
                                      void *arg,
596
 
                                      pj_size_t stack_size,
597
 
                                      unsigned flags,
598
 
                                      pj_thread_t **ptr_thread)
599
 
{
600
 
    PJ_UNUSED_ARG(pool);
601
 
    PJ_UNUSED_ARG(thread_name);
602
 
    PJ_UNUSED_ARG(proc);
603
 
    PJ_UNUSED_ARG(arg);
604
 
    PJ_UNUSED_ARG(stack_size);
605
 
    PJ_UNUSED_ARG(flags);
606
 
    PJ_UNUSED_ARG(ptr_thread);
607
 
 
608
 
    /* Sorry mate, we don't support threading */
609
 
    return PJ_ENOTSUP;
610
 
}
611
 
 
612
 
/*
613
 
 * pj_thread-get_name()
614
 
 */
615
 
PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *p)
616
 
{
617
 
    pj_assert(p == &main_thread);
618
 
    return p->obj_name;
619
 
}
620
 
 
621
 
/*
622
 
 * pj_thread_resume()
623
 
 */
624
 
PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *p)
625
 
{
626
 
    PJ_UNUSED_ARG(p);
627
 
    return PJ_EINVALIDOP;
628
 
}
629
 
 
630
 
/*
631
 
 * pj_thread_this()
632
 
 */
633
 
PJ_DEF(pj_thread_t*) pj_thread_this(void)
634
 
{
635
 
    return &main_thread;
636
 
}
637
 
 
638
 
/*
639
 
 * pj_thread_join()
640
 
 */
641
 
PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *rec)
642
 
{
643
 
    PJ_UNUSED_ARG(rec);
644
 
    return PJ_EINVALIDOP;
645
 
}
646
 
 
647
 
/*
648
 
 * pj_thread_destroy()
649
 
 */
650
 
PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *rec)
651
 
{
652
 
    PJ_UNUSED_ARG(rec);
653
 
    return PJ_EINVALIDOP;
654
 
}
655
 
 
656
 
/*
657
 
 * pj_thread_sleep()
658
 
 */
659
 
PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
660
 
{
661
 
    User::After(msec*1000);
662
 
 
663
 
    return PJ_SUCCESS;
664
 
}
665
 
 
666
 
 
667
 
///////////////////////////////////////////////////////////////////////////////
668
 
/*
669
 
 * pj_thread_local_alloc()
670
 
 */
671
 
 
672
 
PJ_DEF(pj_status_t) pj_thread_local_alloc(long *index)
673
 
{
674
 
    unsigned i;
675
 
 
676
 
    /* Find unused TLS variable */
677
 
    for (i=0; i<PJ_ARRAY_SIZE(tls_vars); ++i) {
678
 
        if (tls_vars[i] == 0)
679
 
            break;
680
 
    }
681
 
 
682
 
    if (i == PJ_ARRAY_SIZE(tls_vars))
683
 
        return PJ_ETOOMANY;
684
 
 
685
 
    tls_vars[i] = 1;
686
 
    *index = i;
687
 
 
688
 
    return PJ_SUCCESS;
689
 
}
690
 
 
691
 
/*
692
 
 * pj_thread_local_free()
693
 
 */
694
 
PJ_DEF(void) pj_thread_local_free(long index)
695
 
{
696
 
    PJ_ASSERT_ON_FAIL(index >= 0 && index < (int)PJ_ARRAY_SIZE(tls_vars) &&
697
 
                     tls_vars[index] != 0, return);
698
 
 
699
 
    tls_vars[index] = 0;
700
 
}
701
 
 
702
 
 
703
 
/*
704
 
 * pj_thread_local_set()
705
 
 */
706
 
PJ_DEF(pj_status_t) pj_thread_local_set(long index, void *value)
707
 
{
708
 
    pj_thread_t *rec = pj_thread_this();
709
 
 
710
 
    PJ_ASSERT_RETURN(index >= 0 && index < (int)PJ_ARRAY_SIZE(tls_vars) &&
711
 
                     tls_vars[index] != 0, PJ_EINVAL);
712
 
 
713
 
    rec->tls_values[index] = value;
714
 
    return PJ_SUCCESS;
715
 
}
716
 
 
717
 
/*
718
 
 * pj_thread_local_get()
719
 
 */
720
 
PJ_DEF(void*) pj_thread_local_get(long index)
721
 
{
722
 
    pj_thread_t *rec = pj_thread_this();
723
 
 
724
 
    PJ_ASSERT_RETURN(index >= 0 && index < (int)PJ_ARRAY_SIZE(tls_vars) &&
725
 
                     tls_vars[index] != 0, NULL);
726
 
 
727
 
    return rec->tls_values[index];
728
 
}
729
 
 
730
 
 
731
 
///////////////////////////////////////////////////////////////////////////////
732
 
/*
733
 
 * Create atomic variable.
734
 
 */
735
 
PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool,
736
 
                                      pj_atomic_value_t initial,
737
 
                                      pj_atomic_t **atomic )
738
 
{
739
 
    *atomic = (pj_atomic_t*)pj_pool_alloc(pool, sizeof(struct pj_atomic_t));
740
 
    (*atomic)->value = initial;
741
 
    return PJ_SUCCESS;
742
 
}
743
 
 
744
 
 
745
 
/*
746
 
 * Destroy atomic variable.
747
 
 */
748
 
PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var )
749
 
{
750
 
    PJ_UNUSED_ARG(atomic_var);
751
 
    return PJ_SUCCESS;
752
 
}
753
 
 
754
 
 
755
 
/*
756
 
 * Set the value of an atomic type, and return the previous value.
757
 
 */
758
 
PJ_DEF(void) pj_atomic_set( pj_atomic_t *atomic_var,
759
 
                            pj_atomic_value_t value)
760
 
{
761
 
    atomic_var->value = value;
762
 
}
763
 
 
764
 
 
765
 
/*
766
 
 * Get the value of an atomic type.
767
 
 */
768
 
PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
769
 
{
770
 
    return atomic_var->value;
771
 
}
772
 
 
773
 
 
774
 
/*
775
 
 * Increment the value of an atomic type.
776
 
 */
777
 
PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
778
 
{
779
 
    ++atomic_var->value;
780
 
}
781
 
 
782
 
 
783
 
/*
784
 
 * Increment the value of an atomic type and get the result.
785
 
 */
786
 
PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)
787
 
{
788
 
    return ++atomic_var->value;
789
 
}
790
 
 
791
 
 
792
 
/*
793
 
 * Decrement the value of an atomic type.
794
 
 */
795
 
PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
796
 
{
797
 
    --atomic_var->value;
798
 
}
799
 
 
800
 
 
801
 
/*
802
 
 * Decrement the value of an atomic type and get the result.
803
 
 */
804
 
PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
805
 
{
806
 
    return --atomic_var->value;
807
 
}
808
 
 
809
 
 
810
 
/*
811
 
 * Add a value to an atomic type.
812
 
 */
813
 
PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
814
 
                            pj_atomic_value_t value)
815
 
{
816
 
    atomic_var->value += value;
817
 
}
818
 
 
819
 
 
820
 
/*
821
 
 * Add a value to an atomic type and get the result.
822
 
 */
823
 
PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
824
 
                                                 pj_atomic_value_t value)
825
 
{
826
 
    atomic_var->value += value;
827
 
    return atomic_var->value;
828
 
}
829
 
 
830
 
 
831
 
 
832
 
/////////////////////////////////////////////////////////////////////////////
833
 
 
834
 
PJ_DEF(pj_status_t) pj_mutex_create( pj_pool_t *pool,
835
 
                                     const char *name,
836
 
                                     int type,
837
 
                                     pj_mutex_t **mutex)
838
 
{
839
 
    PJ_UNUSED_ARG(pool);
840
 
    PJ_UNUSED_ARG(name);
841
 
    PJ_UNUSED_ARG(type);
842
 
 
843
 
    *mutex = DUMMY_MUTEX;
844
 
    return PJ_SUCCESS;
845
 
}
846
 
 
847
 
/*
848
 
 * pj_mutex_create_simple()
849
 
 */
850
 
PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool,
851
 
                                            const char *name,
852
 
                                            pj_mutex_t **mutex )
853
 
{
854
 
    return pj_mutex_create(pool, name, PJ_MUTEX_SIMPLE, mutex);
855
 
}
856
 
 
857
 
 
858
 
PJ_DEF(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
859
 
                                               const char *name,
860
 
                                               pj_mutex_t **mutex )
861
 
{
862
 
    return pj_mutex_create(pool, name, PJ_MUTEX_RECURSE, mutex);
863
 
}
864
 
 
865
 
 
866
 
/*
867
 
 * pj_mutex_lock()
868
 
 */
869
 
PJ_DEF(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex)
870
 
{
871
 
    pj_assert(mutex == DUMMY_MUTEX);
872
 
    return PJ_SUCCESS;
873
 
}
874
 
 
875
 
/*
876
 
 * pj_mutex_trylock()
877
 
 */
878
 
PJ_DEF(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex)
879
 
{
880
 
    pj_assert(mutex == DUMMY_MUTEX);
881
 
    return PJ_SUCCESS;
882
 
}
883
 
 
884
 
/*
885
 
 * pj_mutex_unlock()
886
 
 */
887
 
PJ_DEF(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex)
888
 
{
889
 
    pj_assert(mutex == DUMMY_MUTEX);
890
 
    return PJ_SUCCESS;
891
 
}
892
 
 
893
 
/*
894
 
 * pj_mutex_destroy()
895
 
 */
896
 
PJ_DEF(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex)
897
 
{
898
 
    pj_assert(mutex == DUMMY_MUTEX);
899
 
    return PJ_SUCCESS;
900
 
}
901
 
 
902
 
 
903
 
/////////////////////////////////////////////////////////////////////////////
904
 
/*
905
 
 * RW Mutex
906
 
 */
907
 
#include "os_rwmutex.c"
908
 
 
909
 
 
910
 
/////////////////////////////////////////////////////////////////////////////
911
 
 
912
 
/*
913
 
 * Enter critical section.
914
 
 */
915
 
PJ_DEF(void) pj_enter_critical_section(void)
916
 
{
917
 
    /* Nothing to do */
918
 
}
919
 
 
920
 
 
921
 
/*
922
 
 * Leave critical section.
923
 
 */
924
 
PJ_DEF(void) pj_leave_critical_section(void)
925
 
{
926
 
    /* Nothing to do */
927
 
}
928
 
 
929
 
 
930
 
/////////////////////////////////////////////////////////////////////////////
931
 
 
932
 
/*
933
 
 * Create semaphore.
934
 
 */
935
 
PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool,
936
 
                                   const char *name,
937
 
                                   unsigned initial,
938
 
                                   unsigned max,
939
 
                                   pj_sem_t **p_sem)
940
 
{
941
 
    pj_sem_t *sem;
942
 
 
943
 
    PJ_UNUSED_ARG(name);
944
 
 
945
 
    sem = (pj_sem_t*) pj_pool_zalloc(pool, sizeof(pj_sem_t));
946
 
    sem->value = initial;
947
 
    sem->max = max;
948
 
 
949
 
    *p_sem = sem;
950
 
 
951
 
    return PJ_SUCCESS;
952
 
}
953
 
 
954
 
 
955
 
/*
956
 
 * Wait for semaphore.
957
 
 */
958
 
PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
959
 
{
960
 
    if (sem->value > 0) {
961
 
        sem->value--;
962
 
        return PJ_SUCCESS;
963
 
    } else {
964
 
        pj_assert(!"Unexpected!");
965
 
        return PJ_EINVALIDOP;
966
 
    }
967
 
}
968
 
 
969
 
 
970
 
/*
971
 
 * Try wait for semaphore.
972
 
 */
973
 
PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
974
 
{
975
 
    if (sem->value > 0) {
976
 
        sem->value--;
977
 
        return PJ_SUCCESS;
978
 
    } else {
979
 
        pj_assert(!"Unexpected!");
980
 
        return PJ_EINVALIDOP;
981
 
    }
982
 
}
983
 
 
984
 
 
985
 
/*
986
 
 * Release semaphore.
987
 
 */
988
 
PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
989
 
{
990
 
    sem->value++;
991
 
    return PJ_SUCCESS;
992
 
}
993
 
 
994
 
 
995
 
/*
996
 
 * Destroy semaphore.
997
 
 */
998
 
PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
999
 
{
1000
 
    PJ_UNUSED_ARG(sem);
1001
 
    return PJ_SUCCESS;
1002
 
}
1003
 
 
1004
 
 
1005
 
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK != 0
1006
 
/*
1007
 
 * The implementation of stack checking.
1008
 
 */
1009
 
PJ_DEF(void) pj_thread_check_stack(const char *file, int line)
1010
 
{
1011
 
    char stk_ptr;
1012
 
    pj_uint32_t usage;
1013
 
    pj_thread_t *thread = pj_thread_this();
1014
 
 
1015
 
    pj_assert(thread);
1016
 
 
1017
 
    /* Calculate current usage. */
1018
 
    usage = (&stk_ptr > thread->stk_start) ? &stk_ptr - thread->stk_start :
1019
 
                thread->stk_start - &stk_ptr;
1020
 
 
1021
 
    /* Assert if stack usage is dangerously high. */
1022
 
    pj_assert("STACK OVERFLOW!! " && (usage <= thread->stk_size - 128));
1023
 
 
1024
 
    /* Keep statistic. */
1025
 
    if (usage > thread->stk_max_usage) {
1026
 
        thread->stk_max_usage = usage;
1027
 
        thread->caller_file = file;
1028
 
        thread->caller_line = line;
1029
 
    }
1030
 
}
1031
 
 
1032
 
/*
1033
 
 * Get maximum stack usage statistic.
1034
 
 */
1035
 
PJ_DEF(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread)
1036
 
{
1037
 
    return thread->stk_max_usage;
1038
 
}
1039
 
 
1040
 
/*
1041
 
 * Dump thread stack status.
1042
 
 */
1043
 
PJ_DEF(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,
1044
 
                                             const char **file,
1045
 
                                             int *line)
1046
 
{
1047
 
    pj_assert(thread);
1048
 
 
1049
 
    *file = thread->caller_file;
1050
 
    *line = thread->caller_line;
1051
 
    return 0;
1052
 
}
1053
 
 
1054
 
#endif  /* PJ_OS_HAS_CHECK_STACK */
1055
 
 
1056
 
/*
1057
 
 * pj_run_app()
1058
 
 */
1059
 
PJ_DEF(int) pj_run_app(pj_main_func_ptr main_func, int argc, char *argv[],
1060
 
                       unsigned flags)
1061
 
{
1062
 
    return (*main_func)(argc, argv);
1063
 
}