blob: a5c10df85b4de57acfc2b7308a54f3faf43cf2f4 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#ifndef __PJ_OS_H__
20#define __PJ_OS_H__
21
22/**
23 * @file os.h
24 * @brief OS dependent functions
25 */
26#include <pj/types.h>
27
28PJ_BEGIN_DECL
29
30/**
31 * @defgroup PJ_OS Operating System Dependent Functionality.
32 * @ingroup PJ
33 */
34
35
Benny Prijono92ac4472006-07-22 13:42:56 +000036/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +000037/**
38 * @defgroup PJ_THREAD Threads
39 * @ingroup PJ_OS
40 * @{
41 * This module provides multithreading API.
42 *
43 * \section pj_thread_examples_sec Examples
44 *
45 * For examples, please see:
46 * - \ref page_pjlib_thread_test
47 * - \ref page_pjlib_sleep_test
48 *
49 */
50
51/**
52 * Thread creation flags:
53 * - PJ_THREAD_SUSPENDED: specify that the thread should be created suspended.
54 */
55typedef enum pj_thread_create_flags
56{
57 PJ_THREAD_SUSPENDED = 1
58} pj_thread_create_flags;
59
60
61/**
Benny Prijono9033e312005-11-21 02:08:39 +000062 * Type of thread entry function.
63 */
64typedef int (PJ_THREAD_FUNC pj_thread_proc)(void*);
65
66/**
67 * Size of thread struct.
68 */
69#if !defined(PJ_THREAD_DESC_SIZE)
Benny Prijonod345a652006-07-31 15:10:36 +000070# define PJ_THREAD_DESC_SIZE (64)
Benny Prijono9033e312005-11-21 02:08:39 +000071#endif
72
73/**
74 * Thread structure, to thread's state when the thread is created by external
75 * or native API.
76 */
77typedef long pj_thread_desc[PJ_THREAD_DESC_SIZE];
78
79/**
80 * Get process ID.
81 * @return process ID.
82 */
83PJ_DECL(pj_uint32_t) pj_getpid(void);
84
85/**
86 * Create a new thread.
87 *
88 * @param pool The memory pool from which the thread record
89 * will be allocated from.
90 * @param thread_name The optional name to be assigned to the thread.
91 * @param proc Thread entry function.
92 * @param arg Argument to be passed to the thread entry function.
93 * @param stack_size The size of the stack for the new thread, or ZERO or
94 * PJ_THREAD_DEFAULT_STACK_SIZE to let the
95 * library choose the reasonable size for the stack.
96 * For some systems, the stack will be allocated from
97 * the pool, so the pool must have suitable capacity.
98 * @param flags Flags for thread creation, which is bitmask combination
99 * from enum pj_thread_create_flags.
100 * @param thread Pointer to hold the newly created thread.
101 *
102 * @return PJ_SUCCESS on success, or the error code.
103 */
104PJ_DECL(pj_status_t) pj_thread_create( pj_pool_t *pool,
105 const char *thread_name,
106 pj_thread_proc *proc,
107 void *arg,
108 pj_size_t stack_size,
109 unsigned flags,
110 pj_thread_t **thread );
111
112/**
113 * Register a thread that was created by external or native API to PJLIB.
114 * This function must be called in the context of the thread being registered.
115 * When the thread is created by external function or API call,
116 * it must be 'registered' to PJLIB using pj_thread_register(), so that it can
117 * cooperate with PJLIB's framework. During registration, some data needs to
118 * be maintained, and this data must remain available during the thread's
119 * lifetime.
120 *
121 * @param thread_name The optional name to be assigned to the thread.
122 * @param desc Thread descriptor, which must be available throughout
123 * the lifetime of the thread.
124 * @param thread Pointer to hold the created thread handle.
125 *
126 * @return PJ_SUCCESS on success, or the error code.
127 */
128PJ_DECL(pj_status_t) pj_thread_register ( const char *thread_name,
129 pj_thread_desc desc,
130 pj_thread_t **thread);
131
132/**
Benny Prijonod6b90f52006-08-11 19:25:17 +0000133 * Check if this thread has been registered to PJLIB.
134 *
135 * @return Non-zero if it is registered.
136 */
Benny Prijonoe71c3602006-10-03 17:00:00 +0000137PJ_DECL(pj_bool_t) pj_thread_is_registered(void);
Benny Prijonod6b90f52006-08-11 19:25:17 +0000138
139
140/**
Benny Prijono83c38972007-11-21 14:12:01 +0000141 * Return native handle from pj_thread_t for manipulation using native
142 * OS APIs.
143 *
144 * @param thread PJLIB thread descriptor.
145 *
146 * @return Native thread handle. For example, when the
147 * backend thread uses pthread, this function will
148 * return pointer to pthread_t, and on Windows,
149 * this function will return HANDLE.
150 */
151PJ_DECL(void*) pj_thread_get_os_handle(pj_thread_t *thread);
152
153/**
Benny Prijono9033e312005-11-21 02:08:39 +0000154 * Get thread name.
155 *
156 * @param thread The thread handle.
157 *
158 * @return Thread name as null terminated string.
159 */
160PJ_DECL(const char*) pj_thread_get_name(pj_thread_t *thread);
161
162/**
163 * Resume a suspended thread.
164 *
165 * @param thread The thread handle.
166 *
167 * @return zero on success.
168 */
169PJ_DECL(pj_status_t) pj_thread_resume(pj_thread_t *thread);
170
171/**
172 * Get the current thread.
173 *
174 * @return Thread handle of current thread.
175 */
176PJ_DECL(pj_thread_t*) pj_thread_this(void);
177
178/**
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000179 * Join thread, and block the caller thread until the specified thread exits.
180 * If the specified thread has already been dead, or it does not exist,
181 * the function will return immediately with successfull status.
Benny Prijono9033e312005-11-21 02:08:39 +0000182 *
183 * @param thread The thread handle.
184 *
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000185 * @return PJ_SUCCESS on success.
Benny Prijono9033e312005-11-21 02:08:39 +0000186 */
187PJ_DECL(pj_status_t) pj_thread_join(pj_thread_t *thread);
188
189
190/**
191 * Destroy thread and release resources allocated for the thread.
192 * However, the memory allocated for the pj_thread_t itself will only be released
193 * when the pool used to create the thread is destroyed.
194 *
195 * @param thread The thread handle.
196 *
197 * @return zero on success.
198 */
199PJ_DECL(pj_status_t) pj_thread_destroy(pj_thread_t *thread);
200
201
202/**
203 * Put the current thread to sleep for the specified miliseconds.
204 *
205 * @param msec Miliseconds delay.
206 *
207 * @return zero if successfull.
208 */
209PJ_DECL(pj_status_t) pj_thread_sleep(unsigned msec);
210
211/**
212 * @def PJ_CHECK_STACK()
213 * PJ_CHECK_STACK() macro is used to check the sanity of the stack.
214 * The OS implementation may check that no stack overflow occurs, and
215 * it also may collect statistic about stack usage.
216 */
217#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
218
219# define PJ_CHECK_STACK() pj_thread_check_stack(__FILE__, __LINE__)
220
221/** @internal
222 * The implementation of stack checking.
223 */
224PJ_DECL(void) pj_thread_check_stack(const char *file, int line);
225
226/** @internal
227 * Get maximum stack usage statistic.
228 */
229PJ_DECL(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread);
230
231/** @internal
232 * Dump thread stack status.
233 */
234PJ_DECL(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,
235 const char **file,
236 int *line);
237#else
238
239# define PJ_CHECK_STACK()
240/** pj_thread_get_stack_max_usage() for the thread */
241# define pj_thread_get_stack_max_usage(thread) 0
242/** pj_thread_get_stack_info() for the thread */
243# define pj_thread_get_stack_info(thread,f,l) (*(f)="",*(l)=0)
244#endif /* PJ_OS_HAS_CHECK_STACK */
245
246/**
247 * @}
248 */
249
Benny Prijono92ac4472006-07-22 13:42:56 +0000250/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000251/**
Benny Prijono8ab968f2007-07-20 08:08:30 +0000252 * @defgroup PJ_SYMBIAN_OS Symbian OS Specific
253 * @ingroup PJ_OS
254 * @{
255 * Functionalities specific to Symbian OS.
256 *
257 * Symbian OS strongly discourages the use of polling since this wastes
258 * CPU power, and instead provides Active Object and Active Scheduler
259 * pattern to allow application (in this case, PJLIB) to register asynchronous
260 * tasks. PJLIB port for Symbian complies to this recommended behavior.
261 * As the result, few things have been changed in PJLIB for Symbian:
262 * - the timer heap (see @ref PJ_TIMER) is implemented with active
263 * object framework, and each timer entry registered to the timer
264 * heap will register an Active Object to the Active Scheduler.
265 * Because of this, polling the timer heap with pj_timer_heap_poll()
266 * is no longer necessary, and this function will just evaluate
267 * to nothing.
268 * - the ioqueue (see @ref PJ_IOQUEUE) is also implemented with
269 * active object framework, with each asynchronous operation will
270 * register an Active Object to the Active Scheduler. Because of
271 * this, polling the ioqueue with pj_ioqueue_poll() is no longer
272 * necessary, and this function will just evaluate to nothing.
273 *
274 * Since timer heap and ioqueue polling are no longer necessary, Symbian
275 * application can now poll for all events by calling
276 * \a User::WaitForAnyRequest() and \a CActiveScheduler::RunIfReady().
277 * PJLIB provides a thin wrapper which calls these two functions,
278 * called pj_symbianos_poll().
279 */
280
281/**
282 * Wait the completion of any Symbian active objects. When the timeout
283 * value is not specified (the \a ms_timeout argument is -1), this
284 * function is a thin wrapper which calls \a User::WaitForAnyRequest()
285 * and \a CActiveScheduler::RunIfReady(). If the timeout value is
286 * specified, this function will schedule a timer entry to the timer
287 * heap (which is an Active Object), to limit the wait time for event
288 * occurences. Scheduling a timer entry is an expensive operation,
289 * therefore application should only specify a timeout value when it's
290 * really necessary (for example, when it's not sure there are other
291 * Active Objects currently running in the application).
292 *
293 * @param priority The minimum priority of the Active Objects to
294 * poll, which values are from CActive::TPriority
295 * constants. If -1 is given, CActive::EPriorityStandard.
296 * priority will be used.
297 * @param ms_timeout Optional timeout to wait. Application should
298 * specify -1 to let the function wait indefinitely
299 * for any events.
300 *
301 * @return PJ_TRUE if there have been any events executed
302 * during the polling. This function will only return
303 * PJ_FALSE if \a ms_timeout argument is specified
304 * (i.e. the value is not -1) and there was no event
305 * executed when the timeout timer elapsed.
306 */
307PJ_DECL(pj_bool_t) pj_symbianos_poll(int priority, int ms_timeout);
308
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000309
310/**
311 * This structure declares Symbian OS specific parameters that can be
312 * specified when calling #pj_symbianos_set_params().
313 */
314typedef struct pj_symbianos_params
315{
316 /**
317 * Optional RSocketServ instance to be used by PJLIB. If this
318 * value is NULL, PJLIB will create a new RSocketServ instance
319 * when pj_init() is called.
320 */
321 void *rsocketserv;
322
323 /**
324 * Optional RConnection instance to be used by PJLIB when creating
325 * sockets. If this value is NULL, no RConnection will be
326 * specified when creating sockets.
327 */
328 void *rconnection;
329
330 /**
331 * Optional RHostResolver instance to be used by PJLIB. If this value
332 * is NULL, a new RHostResolver instance will be created when
333 * pj_init() is called.
334 */
335 void *rhostresolver;
336
Benny Prijono62b86eb2007-12-01 08:52:57 +0000337 /**
338 * Optional RHostResolver for IPv6 instance to be used by PJLIB.
339 * If this value is NULL, a new RHostResolver instance will be created
340 * when pj_init() is called.
341 */
342 void *rhostresolver6;
343
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000344} pj_symbianos_params;
345
346/**
347 * Specify Symbian OS parameters to be used by PJLIB. This function MUST
348 * be called before #pj_init() is called.
349 *
350 * @param prm Symbian specific parameters.
351 *
352 * @return PJ_SUCCESS if the parameters can be applied
353 * successfully.
354 */
355PJ_DECL(pj_status_t) pj_symbianos_set_params(pj_symbianos_params *prm);
356
357
Benny Prijono8ab968f2007-07-20 08:08:30 +0000358/**
359 * @}
360 */
361
362/* **************************************************************************/
363/**
Benny Prijono9033e312005-11-21 02:08:39 +0000364 * @defgroup PJ_TLS Thread Local Storage.
365 * @ingroup PJ_OS
366 * @{
367 */
368
369/**
370 * Allocate thread local storage index. The initial value of the variable at
371 * the index is zero.
372 *
373 * @param index Pointer to hold the return value.
374 * @return PJ_SUCCESS on success, or the error code.
375 */
376PJ_DECL(pj_status_t) pj_thread_local_alloc(long *index);
377
378/**
379 * Deallocate thread local variable.
380 *
381 * @param index The variable index.
382 */
383PJ_DECL(void) pj_thread_local_free(long index);
384
385/**
386 * Set the value of thread local variable.
387 *
388 * @param index The index of the variable.
389 * @param value The value.
390 */
391PJ_DECL(pj_status_t) pj_thread_local_set(long index, void *value);
392
393/**
394 * Get the value of thread local variable.
395 *
396 * @param index The index of the variable.
397 * @return The value.
398 */
399PJ_DECL(void*) pj_thread_local_get(long index);
400
401
402/**
403 * @}
404 */
405
406
Benny Prijono92ac4472006-07-22 13:42:56 +0000407/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000408/**
409 * @defgroup PJ_ATOMIC Atomic Variables
410 * @ingroup PJ_OS
411 * @{
412 *
413 * This module provides API to manipulate atomic variables.
414 *
415 * \section pj_atomic_examples_sec Examples
416 *
417 * For some example codes, please see:
418 * - @ref page_pjlib_atomic_test
419 */
420
421
422/**
423 * Create atomic variable.
424 *
425 * @param pool The pool.
426 * @param initial The initial value of the atomic variable.
427 * @param atomic Pointer to hold the atomic variable upon return.
428 *
429 * @return PJ_SUCCESS on success, or the error code.
430 */
431PJ_DECL(pj_status_t) pj_atomic_create( pj_pool_t *pool,
432 pj_atomic_value_t initial,
433 pj_atomic_t **atomic );
434
435/**
436 * Destroy atomic variable.
437 *
438 * @param atomic_var the atomic variable.
439 *
440 * @return PJ_SUCCESS if success.
441 */
442PJ_DECL(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var );
443
444/**
445 * Set the value of an atomic type, and return the previous value.
446 *
447 * @param atomic_var the atomic variable.
448 * @param value value to be set to the variable.
449 */
450PJ_DECL(void) pj_atomic_set( pj_atomic_t *atomic_var,
451 pj_atomic_value_t value);
452
453/**
454 * Get the value of an atomic type.
455 *
456 * @param atomic_var the atomic variable.
457 *
458 * @return the value of the atomic variable.
459 */
460PJ_DECL(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var);
461
462/**
463 * Increment the value of an atomic type.
464 *
465 * @param atomic_var the atomic variable.
466 */
467PJ_DECL(void) pj_atomic_inc(pj_atomic_t *atomic_var);
468
469/**
470 * Increment the value of an atomic type and get the result.
471 *
472 * @param atomic_var the atomic variable.
473 *
474 * @return The incremented value.
475 */
476PJ_DECL(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var);
477
478/**
479 * Decrement the value of an atomic type.
480 *
481 * @param atomic_var the atomic variable.
482 */
483PJ_DECL(void) pj_atomic_dec(pj_atomic_t *atomic_var);
484
485/**
486 * Decrement the value of an atomic type and get the result.
487 *
488 * @param atomic_var the atomic variable.
489 *
490 * @return The decremented value.
491 */
492PJ_DECL(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var);
493
494/**
495 * Add a value to an atomic type.
496 *
497 * @param atomic_var The atomic variable.
498 * @param value Value to be added.
499 */
500PJ_DECL(void) pj_atomic_add( pj_atomic_t *atomic_var,
501 pj_atomic_value_t value);
502
503/**
504 * Add a value to an atomic type and get the result.
505 *
506 * @param atomic_var The atomic variable.
507 * @param value Value to be added.
508 *
509 * @return The result after the addition.
510 */
511PJ_DECL(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
512 pj_atomic_value_t value);
513
514/**
515 * @}
516 */
517
Benny Prijono92ac4472006-07-22 13:42:56 +0000518/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000519/**
520 * @defgroup PJ_MUTEX Mutexes.
521 * @ingroup PJ_OS
522 * @{
523 *
524 * Mutex manipulation. Alternatively, application can use higher abstraction
525 * for lock objects, which provides uniform API for all kinds of lock
526 * mechanisms, including mutex. See @ref PJ_LOCK for more information.
527 */
528
529/**
530 * Mutex types:
531 * - PJ_MUTEX_DEFAULT: default mutex type, which is system dependent.
532 * - PJ_MUTEX_SIMPLE: non-recursive mutex.
Benny Prijono8ab968f2007-07-20 08:08:30 +0000533 * - PJ_MUTEX_RECURSE: recursive mutex.
Benny Prijono9033e312005-11-21 02:08:39 +0000534 */
535typedef enum pj_mutex_type_e
536{
537 PJ_MUTEX_DEFAULT,
538 PJ_MUTEX_SIMPLE,
Benny Prijono92ac4472006-07-22 13:42:56 +0000539 PJ_MUTEX_RECURSE
Benny Prijono9033e312005-11-21 02:08:39 +0000540} pj_mutex_type_e;
541
542
543/**
544 * Create mutex of the specified type.
545 *
546 * @param pool The pool.
547 * @param name Name to be associated with the mutex (for debugging).
548 * @param type The type of the mutex, of type #pj_mutex_type_e.
549 * @param mutex Pointer to hold the returned mutex instance.
550 *
551 * @return PJ_SUCCESS on success, or the error code.
552 */
553PJ_DECL(pj_status_t) pj_mutex_create(pj_pool_t *pool,
554 const char *name,
555 int type,
556 pj_mutex_t **mutex);
557
558/**
559 * Create simple, non-recursive mutex.
560 * This function is a simple wrapper for #pj_mutex_create to create
561 * non-recursive mutex.
562 *
563 * @param pool The pool.
564 * @param name Mutex name.
565 * @param mutex Pointer to hold the returned mutex instance.
566 *
567 * @return PJ_SUCCESS on success, or the error code.
568 */
569PJ_DECL(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,
570 pj_mutex_t **mutex );
571
572/**
573 * Create recursive mutex.
574 * This function is a simple wrapper for #pj_mutex_create to create
575 * recursive mutex.
576 *
577 * @param pool The pool.
578 * @param name Mutex name.
579 * @param mutex Pointer to hold the returned mutex instance.
580 *
581 * @return PJ_SUCCESS on success, or the error code.
582 */
583PJ_DECL(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
584 const char *name,
585 pj_mutex_t **mutex );
586
587/**
588 * Acquire mutex lock.
589 *
590 * @param mutex The mutex.
591 * @return PJ_SUCCESS on success, or the error code.
592 */
593PJ_DECL(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex);
594
595/**
596 * Release mutex lock.
597 *
598 * @param mutex The mutex.
599 * @return PJ_SUCCESS on success, or the error code.
600 */
601PJ_DECL(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex);
602
603/**
604 * Try to acquire mutex lock.
605 *
606 * @param mutex The mutex.
607 * @return PJ_SUCCESS on success, or the error code if the
608 * lock couldn't be acquired.
609 */
610PJ_DECL(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex);
611
612/**
613 * Destroy mutex.
614 *
615 * @param mutex Te mutex.
616 * @return PJ_SUCCESS on success, or the error code.
617 */
618PJ_DECL(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex);
619
620/**
621 * Determine whether calling thread is owning the mutex (only available when
622 * PJ_DEBUG is set).
623 * @param mutex The mutex.
624 * @return Non-zero if yes.
625 */
626#if defined(PJ_DEBUG) && PJ_DEBUG != 0
627 PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);
628#else
629# define pj_mutex_is_locked(mutex) 1
630#endif
631
632/**
633 * @}
634 */
635
Benny Prijono92ac4472006-07-22 13:42:56 +0000636/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000637/**
Benny Prijono0ca04b62005-12-30 23:50:15 +0000638 * @defgroup PJ_RW_MUTEX Reader/Writer Mutex
639 * @ingroup PJ_OS
640 * @{
641 * Reader/writer mutex is a classic synchronization object where multiple
642 * readers can acquire the mutex, but only a single writer can acquire the
643 * mutex.
644 */
Benny Prijono294c2532006-06-16 16:52:51 +0000645
646/**
647 * Opaque declaration for reader/writer mutex.
648 * Reader/writer mutex is a classic synchronization object where multiple
649 * readers can acquire the mutex, but only a single writer can acquire the
650 * mutex.
651 */
Benny Prijono0ca04b62005-12-30 23:50:15 +0000652typedef struct pj_rwmutex_t pj_rwmutex_t;
653
654/**
655 * Create reader/writer mutex.
656 *
657 * @param pool Pool to allocate memory for the mutex.
658 * @param name Name to be assigned to the mutex.
659 * @param mutex Pointer to receive the newly created mutex.
660 *
661 * @return PJ_SUCCESS on success, or the error code.
662 */
663PJ_DECL(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
664 pj_rwmutex_t **mutex);
665
666/**
667 * Lock the mutex for reading.
668 *
669 * @param mutex The mutex.
670 * @return PJ_SUCCESS on success, or the error code.
671 */
672PJ_DECL(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex);
673
674/**
675 * Lock the mutex for writing.
676 *
677 * @param mutex The mutex.
678 * @return PJ_SUCCESS on success, or the error code.
679 */
680PJ_DECL(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex);
681
682/**
683 * Release read lock.
684 *
685 * @param mutex The mutex.
686 * @return PJ_SUCCESS on success, or the error code.
687 */
688PJ_DECL(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex);
689
690/**
691 * Release write lock.
692 *
693 * @param mutex The mutex.
694 * @return PJ_SUCCESS on success, or the error code.
695 */
696PJ_DECL(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex);
697
698/**
699 * Destroy reader/writer mutex.
700 *
701 * @param mutex The mutex.
702 * @return PJ_SUCCESS on success, or the error code.
703 */
704PJ_DECL(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex);
705
706
707/**
708 * @}
709 */
710
711
Benny Prijono92ac4472006-07-22 13:42:56 +0000712/* **************************************************************************/
Benny Prijono0ca04b62005-12-30 23:50:15 +0000713/**
Benny Prijono9033e312005-11-21 02:08:39 +0000714 * @defgroup PJ_CRIT_SEC Critical sections.
715 * @ingroup PJ_OS
716 * @{
717 * Critical section protection can be used to protect regions where:
718 * - mutual exclusion protection is needed.
719 * - it's rather too expensive to create a mutex.
720 * - the time spent in the region is very very brief.
721 *
722 * Critical section is a global object, and it prevents any threads from
723 * entering any regions that are protected by critical section once a thread
724 * is already in the section.
725 *
726 * Critial section is \a not recursive!
727 *
728 * Application <b>MUST NOT</b> call any functions that may cause current
729 * thread to block (such as allocating memory, performing I/O, locking mutex,
730 * etc.) while holding the critical section.
731 */
732/**
733 * Enter critical section.
734 */
735PJ_DECL(void) pj_enter_critical_section(void);
736
737/**
738 * Leave critical section.
739 */
740PJ_DECL(void) pj_leave_critical_section(void);
741
742/**
743 * @}
744 */
745
Benny Prijono92ac4472006-07-22 13:42:56 +0000746/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000747#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
748/**
749 * @defgroup PJ_SEM Semaphores.
750 * @ingroup PJ_OS
751 * @{
752 *
753 * This module provides abstraction for semaphores, where available.
754 */
755
756/**
757 * Create semaphore.
758 *
759 * @param pool The pool.
760 * @param name Name to be assigned to the semaphore (for logging purpose)
761 * @param initial The initial count of the semaphore.
762 * @param max The maximum count of the semaphore.
763 * @param sem Pointer to hold the semaphore created.
764 *
765 * @return PJ_SUCCESS on success, or the error code.
766 */
767PJ_DECL(pj_status_t) pj_sem_create( pj_pool_t *pool,
768 const char *name,
769 unsigned initial,
770 unsigned max,
771 pj_sem_t **sem);
772
773/**
774 * Wait for semaphore.
775 *
776 * @param sem The semaphore.
777 *
778 * @return PJ_SUCCESS on success, or the error code.
779 */
780PJ_DECL(pj_status_t) pj_sem_wait(pj_sem_t *sem);
781
782/**
783 * Try wait for semaphore.
784 *
785 * @param sem The semaphore.
786 *
787 * @return PJ_SUCCESS on success, or the error code.
788 */
789PJ_DECL(pj_status_t) pj_sem_trywait(pj_sem_t *sem);
790
791/**
792 * Release semaphore.
793 *
794 * @param sem The semaphore.
795 *
796 * @return PJ_SUCCESS on success, or the error code.
797 */
798PJ_DECL(pj_status_t) pj_sem_post(pj_sem_t *sem);
799
800/**
801 * Destroy semaphore.
802 *
803 * @param sem The semaphore.
804 *
805 * @return PJ_SUCCESS on success, or the error code.
806 */
807PJ_DECL(pj_status_t) pj_sem_destroy(pj_sem_t *sem);
808
809/**
810 * @}
811 */
812#endif /* PJ_HAS_SEMAPHORE */
813
814
Benny Prijono92ac4472006-07-22 13:42:56 +0000815/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000816#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
817/**
818 * @defgroup PJ_EVENT Event Object.
819 * @ingroup PJ_OS
820 * @{
821 *
822 * This module provides abstraction to event object (e.g. Win32 Event) where
823 * available. Event objects can be used for synchronization among threads.
824 */
825
826/**
827 * Create event object.
828 *
829 * @param pool The pool.
830 * @param name The name of the event object (for logging purpose).
831 * @param manual_reset Specify whether the event is manual-reset
832 * @param initial Specify the initial state of the event object.
833 * @param event Pointer to hold the returned event object.
834 *
835 * @return event handle, or NULL if failed.
836 */
837PJ_DECL(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name,
838 pj_bool_t manual_reset, pj_bool_t initial,
839 pj_event_t **event);
840
841/**
842 * Wait for event to be signaled.
843 *
844 * @param event The event object.
845 *
846 * @return zero if successfull.
847 */
848PJ_DECL(pj_status_t) pj_event_wait(pj_event_t *event);
849
850/**
851 * Try wait for event object to be signalled.
852 *
853 * @param event The event object.
854 *
855 * @return zero if successfull.
856 */
857PJ_DECL(pj_status_t) pj_event_trywait(pj_event_t *event);
858
859/**
860 * Set the event object state to signaled. For auto-reset event, this
861 * will only release the first thread that are waiting on the event. For
862 * manual reset event, the state remains signaled until the event is reset.
863 * If there is no thread waiting on the event, the event object state
864 * remains signaled.
865 *
866 * @param event The event object.
867 *
868 * @return zero if successfull.
869 */
870PJ_DECL(pj_status_t) pj_event_set(pj_event_t *event);
871
872/**
873 * Set the event object to signaled state to release appropriate number of
874 * waiting threads and then reset the event object to non-signaled. For
875 * manual-reset event, this function will release all waiting threads. For
876 * auto-reset event, this function will only release one waiting thread.
877 *
878 * @param event The event object.
879 *
880 * @return zero if successfull.
881 */
882PJ_DECL(pj_status_t) pj_event_pulse(pj_event_t *event);
883
884/**
885 * Set the event object state to non-signaled.
886 *
887 * @param event The event object.
888 *
889 * @return zero if successfull.
890 */
891PJ_DECL(pj_status_t) pj_event_reset(pj_event_t *event);
892
893/**
894 * Destroy the event object.
895 *
896 * @param event The event object.
897 *
898 * @return zero if successfull.
899 */
900PJ_DECL(pj_status_t) pj_event_destroy(pj_event_t *event);
901
902/**
903 * @}
904 */
905#endif /* PJ_HAS_EVENT_OBJ */
906
Benny Prijono92ac4472006-07-22 13:42:56 +0000907/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000908/**
909 * @addtogroup PJ_TIME Time Data Type and Manipulation.
910 * @ingroup PJ_OS
911 * @{
912 * This module provides API for manipulating time.
913 *
914 * \section pj_time_examples_sec Examples
915 *
916 * For examples, please see:
917 * - \ref page_pjlib_sleep_test
918 */
919
920/**
921 * Get current time of day in local representation.
922 *
923 * @param tv Variable to store the result.
924 *
925 * @return zero if successfull.
926 */
927PJ_DECL(pj_status_t) pj_gettimeofday(pj_time_val *tv);
928
929
930/**
931 * Parse time value into date/time representation.
932 *
933 * @param tv The time.
934 * @param pt Variable to store the date time result.
935 *
936 * @return zero if successfull.
937 */
938PJ_DECL(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt);
939
940/**
941 * Encode date/time to time value.
942 *
943 * @param pt The date/time.
944 * @param tv Variable to store time value result.
945 *
946 * @return zero if successfull.
947 */
948PJ_DECL(pj_status_t) pj_time_encode(const pj_parsed_time *pt, pj_time_val *tv);
949
950/**
951 * Convert local time to GMT.
952 *
953 * @param tv Time to convert.
954 *
955 * @return zero if successfull.
956 */
957PJ_DECL(pj_status_t) pj_time_local_to_gmt(pj_time_val *tv);
958
959/**
960 * Convert GMT to local time.
961 *
962 * @param tv Time to convert.
963 *
964 * @return zero if successfull.
965 */
966PJ_DECL(pj_status_t) pj_time_gmt_to_local(pj_time_val *tv);
967
968/**
969 * @}
970 */
971
Benny Prijono92ac4472006-07-22 13:42:56 +0000972/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000973#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0
974
975/**
976 * @defgroup PJ_TERM Terminal
977 * @ingroup PJ_OS
978 * @{
979 */
980
981/**
982 * Set current terminal color.
983 *
984 * @param color The RGB color.
985 *
986 * @return zero on success.
987 */
988PJ_DECL(pj_status_t) pj_term_set_color(pj_color_t color);
989
990/**
991 * Get current terminal foreground color.
992 *
993 * @return RGB color.
994 */
995PJ_DECL(pj_color_t) pj_term_get_color(void);
996
997/**
998 * @}
999 */
1000
1001#endif /* PJ_TERM_HAS_COLOR */
1002
Benny Prijono92ac4472006-07-22 13:42:56 +00001003/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +00001004/**
1005 * @defgroup PJ_TIMESTAMP High Resolution Timestamp
1006 * @ingroup PJ_OS
1007 * @{
1008 *
1009 * PJLIB provides <b>High Resolution Timestamp</b> API to access highest
1010 * resolution timestamp value provided by the platform. The API is usefull
1011 * to measure precise elapsed time, and can be used in applications such
1012 * as profiling.
1013 *
1014 * The timestamp value is represented in cycles, and can be related to
1015 * normal time (in seconds or sub-seconds) using various functions provided.
1016 *
1017 * \section pj_timestamp_examples_sec Examples
1018 *
1019 * For examples, please see:
1020 * - \ref page_pjlib_sleep_test
1021 * - \ref page_pjlib_timestamp_test
1022 */
1023
1024/*
1025 * High resolution timer.
1026 */
1027#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
1028
1029/**
Benny Prijono9033e312005-11-21 02:08:39 +00001030 * Acquire high resolution timer value. The time value are stored
1031 * in cycles.
1032 *
1033 * @param ts High resolution timer value.
1034 * @return PJ_SUCCESS or the appropriate error code.
1035 *
1036 * @see pj_get_timestamp_freq().
1037 */
1038PJ_DECL(pj_status_t) pj_get_timestamp(pj_timestamp *ts);
1039
1040/**
1041 * Get high resolution timer frequency, in cycles per second.
1042 *
1043 * @param freq Timer frequency, in cycles per second.
1044 * @return PJ_SUCCESS or the appropriate error code.
1045 */
1046PJ_DECL(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq);
1047
1048/**
Benny Prijonoc357d642007-01-20 05:14:24 +00001049 * Set timestamp from 32bit values.
1050 * @param t The timestamp to be set.
1051 * @param hi The high 32bit part.
1052 * @param lo The low 32bit part.
1053 */
1054PJ_INLINE(void) pj_set_timestamp32(pj_timestamp *t, pj_uint32_t hi,
1055 pj_uint32_t lo)
1056{
1057 t->u32.hi = hi;
1058 t->u32.lo = lo;
1059}
1060
Benny Prijono6f86e7c2007-04-02 11:28:41 +00001061
1062/**
1063 * Compare timestamp t1 and t2.
1064 * @param t1 t1.
1065 * @param t2 t2.
1066 * @return -1 if (t1 < t2), 1 if (t1 > t2), or 0 if (t1 == t2)
1067 */
1068PJ_INLINE(int) pj_cmp_timestamp(const pj_timestamp *t1, const pj_timestamp *t2)
1069{
1070#if PJ_HAS_INT64
1071 if (t1->u64 < t2->u64)
1072 return -1;
1073 else if (t1->u64 > t2->u64)
1074 return 1;
1075 else
1076 return 0;
1077#else
1078 if (t1->u32.hi < t2->u32.hi ||
1079 (t1->u32.hi == t2->u32.hi && t1->u32.lo < t2->u32.lo))
1080 return -1;
1081 else if (t1->u32.hi > t2->u32.hi ||
1082 (t1->u32.hi == t2->u32.hi && t1->u32.lo > t2->u32.lo))
1083 return 1;
1084 else
1085 return 0;
1086#endif
1087}
1088
1089
Benny Prijonoc357d642007-01-20 05:14:24 +00001090/**
Benny Prijono9033e312005-11-21 02:08:39 +00001091 * Add timestamp t2 to t1.
1092 * @param t1 t1.
1093 * @param t2 t2.
1094 */
1095PJ_INLINE(void) pj_add_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
1096{
1097#if PJ_HAS_INT64
1098 t1->u64 += t2->u64;
1099#else
1100 pj_uint32_t old = t1->u32.lo;
1101 t1->u32.hi += t2->u32.hi;
1102 t1->u32.lo += t2->u32.lo;
1103 if (t1->u32.lo < old)
1104 ++t1->u32.hi;
1105#endif
1106}
1107
1108/**
Benny Prijonoc357d642007-01-20 05:14:24 +00001109 * Add timestamp t2 to t1.
1110 * @param t1 t1.
1111 * @param t2 t2.
1112 */
1113PJ_INLINE(void) pj_add_timestamp32(pj_timestamp *t1, pj_uint32_t t2)
1114{
1115#if PJ_HAS_INT64
1116 t1->u64 += t2;
1117#else
1118 pj_uint32_t old = t1->u32.lo;
1119 t1->u32.lo += t2;
1120 if (t1->u32.lo < old)
1121 ++t1->u32.hi;
1122#endif
1123}
1124
1125/**
Benny Prijono9033e312005-11-21 02:08:39 +00001126 * Substract timestamp t2 from t1.
1127 * @param t1 t1.
1128 * @param t2 t2.
1129 */
1130PJ_INLINE(void) pj_sub_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
1131{
1132#if PJ_HAS_INT64
1133 t1->u64 -= t2->u64;
1134#else
1135 t1->u32.hi -= t2->u32.hi;
1136 if (t1->u32.lo >= t2->u32.lo)
1137 t1->u32.lo -= t2->u32.lo;
1138 else {
1139 t1->u32.lo -= t2->u32.lo;
1140 --t1->u32.hi;
1141 }
1142#endif
1143}
1144
1145/**
Benny Prijonoc357d642007-01-20 05:14:24 +00001146 * Substract timestamp t2 from t1.
1147 * @param t1 t1.
1148 * @param t2 t2.
1149 */
1150PJ_INLINE(void) pj_sub_timestamp32(pj_timestamp *t1, pj_uint32_t t2)
1151{
1152#if PJ_HAS_INT64
1153 t1->u64 -= t2;
1154#else
1155 if (t1->u32.lo >= t2)
1156 t1->u32.lo -= t2;
1157 else {
1158 t1->u32.lo -= t2;
1159 --t1->u32.hi;
1160 }
1161#endif
1162}
1163
1164/**
1165 * Get the timestamp difference between t2 and t1 (that is t2 minus t1),
1166 * and return a 32bit signed integer difference.
1167 */
1168PJ_INLINE(pj_int32_t) pj_timestamp_diff32(const pj_timestamp *t1,
1169 const pj_timestamp *t2)
1170{
1171 /* Be careful with the signess (I think!) */
1172#if PJ_HAS_INT64
1173 pj_int64_t diff = t2->u64 - t1->u64;
1174 return (pj_int32_t) diff;
1175#else
1176 pj_int32 diff = t2->u32.lo - t1->u32.lo;
1177 return diff;
1178#endif
1179}
1180
1181
1182/**
Benny Prijono9033e312005-11-21 02:08:39 +00001183 * Calculate the elapsed time, and store it in pj_time_val.
1184 * This function calculates the elapsed time using highest precision
1185 * calculation that is available for current platform, considering
1186 * whether floating point or 64-bit precision arithmetic is available.
1187 * For maximum portability, application should prefer to use this function
1188 * rather than calculating the elapsed time by itself.
1189 *
1190 * @param start The starting timestamp.
1191 * @param stop The end timestamp.
1192 *
1193 * @return Elapsed time as #pj_time_val.
1194 *
1195 * @see pj_elapsed_usec(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1196 */
1197PJ_DECL(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
1198 const pj_timestamp *stop );
1199
1200/**
Benny Prijono99683ae2005-11-21 16:59:47 +00001201 * Calculate the elapsed time as 32-bit miliseconds.
1202 * This function calculates the elapsed time using highest precision
1203 * calculation that is available for current platform, considering
1204 * whether floating point or 64-bit precision arithmetic is available.
1205 * For maximum portability, application should prefer to use this function
1206 * rather than calculating the elapsed time by itself.
1207 *
1208 * @param start The starting timestamp.
1209 * @param stop The end timestamp.
1210 *
1211 * @return Elapsed time in milisecond.
1212 *
1213 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1214 */
1215PJ_DECL(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
1216 const pj_timestamp *stop );
1217
1218/**
Benny Prijono9033e312005-11-21 02:08:39 +00001219 * Calculate the elapsed time in 32-bit microseconds.
1220 * This function calculates the elapsed time using highest precision
1221 * calculation that is available for current platform, considering
1222 * whether floating point or 64-bit precision arithmetic is available.
1223 * For maximum portability, application should prefer to use this function
1224 * rather than calculating the elapsed time by itself.
1225 *
1226 * @param start The starting timestamp.
1227 * @param stop The end timestamp.
1228 *
1229 * @return Elapsed time in microsecond.
1230 *
1231 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1232 */
1233PJ_DECL(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
1234 const pj_timestamp *stop );
1235
1236/**
1237 * Calculate the elapsed time in 32-bit nanoseconds.
1238 * This function calculates the elapsed time using highest precision
1239 * calculation that is available for current platform, considering
1240 * whether floating point or 64-bit precision arithmetic is available.
1241 * For maximum portability, application should prefer to use this function
1242 * rather than calculating the elapsed time by itself.
1243 *
1244 * @param start The starting timestamp.
1245 * @param stop The end timestamp.
1246 *
1247 * @return Elapsed time in nanoseconds.
1248 *
1249 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_usec()
1250 */
1251PJ_DECL(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
1252 const pj_timestamp *stop );
1253
1254/**
1255 * Calculate the elapsed time in 32-bit cycles.
1256 * This function calculates the elapsed time using highest precision
1257 * calculation that is available for current platform, considering
1258 * whether floating point or 64-bit precision arithmetic is available.
1259 * For maximum portability, application should prefer to use this function
1260 * rather than calculating the elapsed time by itself.
1261 *
1262 * @param start The starting timestamp.
1263 * @param stop The end timestamp.
1264 *
1265 * @return Elapsed time in cycles.
1266 *
1267 * @see pj_elapsed_usec(), pj_elapsed_time(), pj_elapsed_nanosec()
1268 */
1269PJ_DECL(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
1270 const pj_timestamp *stop );
1271
1272
1273#endif /* PJ_HAS_HIGH_RES_TIMER */
1274
1275/** @} */
1276
1277
Benny Prijono92ac4472006-07-22 13:42:56 +00001278/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +00001279/**
1280 * Internal PJLIB function to initialize the threading subsystem.
1281 * @return PJ_SUCCESS or the appropriate error code.
1282 */
1283pj_status_t pj_thread_init(void);
1284
1285
1286PJ_END_DECL
1287
1288#endif /* __PJ_OS_H__ */
1289