blob: d6a1df22f3a97570619adacf032c879413eb0eea [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id$ */
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
52struct 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
67struct pj_atomic_t
68{
69 pj_atomic_value_t value;
70};
71
72struct pj_sem_t
73{
74 int value;
75 int max;
76};
77
78/* Flag and reference counter for PJLIB instance */
79static int initialized;
80
81/* Flags to indicate which TLS variables have been used */
82static int tls_vars[PJ_MAX_TLS];
83
84/* atexit handlers */
85static unsigned atexit_count;
86static void (*atexit_func[32])(void);
87
88
89/////////////////////////////////////////////////////////////////////////////
90//
91// CPjTimeoutTimer implementation
92//
93
94CPjTimeoutTimer::CPjTimeoutTimer()
95: CActive(PJ_SYMBIAN_TIMER_PRIORITY), hasTimedOut_(PJ_FALSE)
96{
97}
98
99CPjTimeoutTimer::~CPjTimeoutTimer()
100{
101 Cancel();
102 timer_.Close();
103}
104
105void CPjTimeoutTimer::ConstructL()
106{
107 hasTimedOut_ = PJ_FALSE;
108 timer_.CreateLocal();
109 CActiveScheduler::Add(this);
110}
111
112CPjTimeoutTimer *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
124void CPjTimeoutTimer::StartTimer(TUint miliSeconds)
125{
126 Cancel();
127
128 hasTimedOut_ = PJ_FALSE;
129 timer_.After(iStatus, miliSeconds * 1000);
130 SetActive();
131}
132
133bool CPjTimeoutTimer::HasTimedOut() const
134{
135 return hasTimedOut_ != 0;
136}
137
138void CPjTimeoutTimer::RunL()
139{
140 hasTimedOut_ = PJ_TRUE;
141}
142
143void CPjTimeoutTimer::DoCancel()
144{
145 timer_.Cancel();
146}
147
148TInt CPjTimeoutTimer::RunError(TInt aError)
149{
150 PJ_UNUSED_ARG(aError);
151 return KErrNone;
152}
153
154
155
156/////////////////////////////////////////////////////////////////////////////
157//
158// PjSymbianOS implementation
159//
160
161PjSymbianOS::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
171void 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
180PjSymbianOS *PjSymbianOS::Instance()
181{
182 static PjSymbianOS instance_;
183 return &instance_;
184}
185
186
187// Initialize
188TInt 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
245on_error:
246 Shutdown();
247 return err;
248}
249
250// Shutdown
251void 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
281TInt 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
292TInt 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
308PJ_DEF(pj_uint32_t) pj_getpid(void)
309{
310 return 0;
311}
312
313
314/* Set Symbian specific parameters */
315PJ_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 */
324PJ_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 */
334PJ_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
385on_error:
386 pj_shutdown();
387 return PJ_RETURN_OS_ERROR(err);
388}
389
390
391PJ_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
402PJ_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
430class CPollTimeoutTimer : public CActive
431{
432public:
433 static CPollTimeoutTimer* NewL(int msec, TInt prio);
434 ~CPollTimeoutTimer();
435
436 virtual void RunL();
437 virtual void DoCancel();
438
439private:
440 RTimer rtimer_;
441
442 explicit CPollTimeoutTimer(TInt prio);
443 void ConstructL(int msec);
444};
445
446CPollTimeoutTimer::CPollTimeoutTimer(TInt prio)
447: CActive(prio)
448{
449}
450
451
452CPollTimeoutTimer::~CPollTimeoutTimer()
453{
454 rtimer_.Close();
455}
456
457void CPollTimeoutTimer::ConstructL(int msec)
458{
459 rtimer_.CreateLocal();
460 CActiveScheduler::Add(this);
461 rtimer_.After(iStatus, msec*1000);
462 SetActive();
463}
464
465CPollTimeoutTimer* 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
475void CPollTimeoutTimer::RunL()
476{
477}
478
479void CPollTimeoutTimer::DoCancel()
480{
481 rtimer_.Cancel();
482}
483
484
485/*
486 * Wait the completion of any Symbian active objects.
487 */
488PJ_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 */
519PJ_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 */
528PJ_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 */
538PJ_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 */
549PJ_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 */
559PJ_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 */
569PJ_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 */
578PJ_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 */
592PJ_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 */
615PJ_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 */
624PJ_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 */
633PJ_DEF(pj_thread_t*) pj_thread_this(void)
634{
635 return &main_thread;
636}
637
638/*
639 * pj_thread_join()
640 */
641PJ_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 */
650PJ_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 */
659PJ_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
672PJ_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 */
694PJ_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 */
706PJ_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 */
720PJ_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 */
735PJ_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 */
748PJ_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 */
758PJ_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 */
768PJ_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 */
777PJ_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 */
786PJ_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 */
795PJ_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 */
804PJ_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 */
813PJ_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 */
823PJ_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
834PJ_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 */
850PJ_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
858PJ_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 */
869PJ_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 */
878PJ_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 */
887PJ_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 */
896PJ_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 */
915PJ_DEF(void) pj_enter_critical_section(void)
916{
917 /* Nothing to do */
918}
919
920
921/*
922 * Leave critical section.
923 */
924PJ_DEF(void) pj_leave_critical_section(void)
925{
926 /* Nothing to do */
927}
928
929
930/////////////////////////////////////////////////////////////////////////////
931
932/*
933 * Create semaphore.
934 */
935PJ_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 */
958PJ_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 */
973PJ_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 */
988PJ_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 */
998PJ_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 */
1009PJ_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 */
1035PJ_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 */
1043PJ_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 */
1059PJ_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}