blob: 0bd1863838783b95df3e9f276a0a3e2b6c61d402 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00005 *
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#ifndef __PJ_OS_H__
21#define __PJ_OS_H__
22
23/**
24 * @file os.h
25 * @brief OS dependent functions
26 */
27#include <pj/types.h>
28
29PJ_BEGIN_DECL
30
31/**
32 * @defgroup PJ_OS Operating System Dependent Functionality.
Benny Prijono9033e312005-11-21 02:08:39 +000033 */
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 Prijono8f7adf72008-03-04 14:45:19 +0000141 * Get thread priority value for the thread.
142 *
143 * @param thread Thread handle.
144 *
145 * @return Thread priority value, or -1 on error.
146 */
147PJ_DECL(int) pj_thread_get_prio(pj_thread_t *thread);
148
149
150/**
151 * Set the thread priority. The priority value must be in the priority
152 * value range, which can be retrieved with #pj_thread_get_prio_min() and
153 * #pj_thread_get_prio_max() functions.
154 *
155 * @param thread Thread handle.
156 * @param prio New priority to be set to the thread.
157 *
158 * @return PJ_SUCCESS on success or the error code.
159 */
160PJ_DECL(pj_status_t) pj_thread_set_prio(pj_thread_t *thread, int prio);
161
162/**
163 * Get the lowest priority value available for this thread.
164 *
165 * @param thread Thread handle.
166 * @return Minimum thread priority value, or -1 on error.
167 */
168PJ_DECL(int) pj_thread_get_prio_min(pj_thread_t *thread);
169
170
171/**
172 * Get the highest priority value available for this thread.
173 *
174 * @param thread Thread handle.
175 * @return Minimum thread priority value, or -1 on error.
176 */
177PJ_DECL(int) pj_thread_get_prio_max(pj_thread_t *thread);
178
179
180/**
Benny Prijono83c38972007-11-21 14:12:01 +0000181 * Return native handle from pj_thread_t for manipulation using native
182 * OS APIs.
183 *
184 * @param thread PJLIB thread descriptor.
185 *
186 * @return Native thread handle. For example, when the
187 * backend thread uses pthread, this function will
188 * return pointer to pthread_t, and on Windows,
189 * this function will return HANDLE.
190 */
191PJ_DECL(void*) pj_thread_get_os_handle(pj_thread_t *thread);
192
193/**
Benny Prijono9033e312005-11-21 02:08:39 +0000194 * Get thread name.
195 *
196 * @param thread The thread handle.
197 *
198 * @return Thread name as null terminated string.
199 */
200PJ_DECL(const char*) pj_thread_get_name(pj_thread_t *thread);
201
202/**
203 * Resume a suspended thread.
204 *
205 * @param thread The thread handle.
206 *
207 * @return zero on success.
208 */
209PJ_DECL(pj_status_t) pj_thread_resume(pj_thread_t *thread);
210
211/**
212 * Get the current thread.
213 *
214 * @return Thread handle of current thread.
215 */
216PJ_DECL(pj_thread_t*) pj_thread_this(void);
217
218/**
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000219 * Join thread, and block the caller thread until the specified thread exits.
220 * If the specified thread has already been dead, or it does not exist,
221 * the function will return immediately with successfull status.
Benny Prijono9033e312005-11-21 02:08:39 +0000222 *
223 * @param thread The thread handle.
224 *
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000225 * @return PJ_SUCCESS on success.
Benny Prijono9033e312005-11-21 02:08:39 +0000226 */
227PJ_DECL(pj_status_t) pj_thread_join(pj_thread_t *thread);
228
229
230/**
231 * Destroy thread and release resources allocated for the thread.
232 * However, the memory allocated for the pj_thread_t itself will only be released
233 * when the pool used to create the thread is destroyed.
234 *
235 * @param thread The thread handle.
236 *
237 * @return zero on success.
238 */
239PJ_DECL(pj_status_t) pj_thread_destroy(pj_thread_t *thread);
240
241
242/**
243 * Put the current thread to sleep for the specified miliseconds.
244 *
245 * @param msec Miliseconds delay.
246 *
247 * @return zero if successfull.
248 */
249PJ_DECL(pj_status_t) pj_thread_sleep(unsigned msec);
250
251/**
252 * @def PJ_CHECK_STACK()
253 * PJ_CHECK_STACK() macro is used to check the sanity of the stack.
254 * The OS implementation may check that no stack overflow occurs, and
255 * it also may collect statistic about stack usage.
256 */
257#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
258
259# define PJ_CHECK_STACK() pj_thread_check_stack(__FILE__, __LINE__)
260
261/** @internal
262 * The implementation of stack checking.
263 */
264PJ_DECL(void) pj_thread_check_stack(const char *file, int line);
265
266/** @internal
267 * Get maximum stack usage statistic.
268 */
269PJ_DECL(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread);
270
271/** @internal
272 * Dump thread stack status.
273 */
274PJ_DECL(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,
275 const char **file,
276 int *line);
277#else
278
279# define PJ_CHECK_STACK()
280/** pj_thread_get_stack_max_usage() for the thread */
281# define pj_thread_get_stack_max_usage(thread) 0
282/** pj_thread_get_stack_info() for the thread */
283# define pj_thread_get_stack_info(thread,f,l) (*(f)="",*(l)=0)
284#endif /* PJ_OS_HAS_CHECK_STACK */
285
286/**
287 * @}
288 */
289
Benny Prijono92ac4472006-07-22 13:42:56 +0000290/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000291/**
Benny Prijono8ab968f2007-07-20 08:08:30 +0000292 * @defgroup PJ_SYMBIAN_OS Symbian OS Specific
293 * @ingroup PJ_OS
294 * @{
295 * Functionalities specific to Symbian OS.
296 *
297 * Symbian OS strongly discourages the use of polling since this wastes
298 * CPU power, and instead provides Active Object and Active Scheduler
299 * pattern to allow application (in this case, PJLIB) to register asynchronous
300 * tasks. PJLIB port for Symbian complies to this recommended behavior.
301 * As the result, few things have been changed in PJLIB for Symbian:
302 * - the timer heap (see @ref PJ_TIMER) is implemented with active
303 * object framework, and each timer entry registered to the timer
304 * heap will register an Active Object to the Active Scheduler.
305 * Because of this, polling the timer heap with pj_timer_heap_poll()
306 * is no longer necessary, and this function will just evaluate
307 * to nothing.
308 * - the ioqueue (see @ref PJ_IOQUEUE) is also implemented with
309 * active object framework, with each asynchronous operation will
310 * register an Active Object to the Active Scheduler. Because of
311 * this, polling the ioqueue with pj_ioqueue_poll() is no longer
312 * necessary, and this function will just evaluate to nothing.
313 *
314 * Since timer heap and ioqueue polling are no longer necessary, Symbian
315 * application can now poll for all events by calling
316 * \a User::WaitForAnyRequest() and \a CActiveScheduler::RunIfReady().
317 * PJLIB provides a thin wrapper which calls these two functions,
318 * called pj_symbianos_poll().
319 */
320
321/**
322 * Wait the completion of any Symbian active objects. When the timeout
323 * value is not specified (the \a ms_timeout argument is -1), this
324 * function is a thin wrapper which calls \a User::WaitForAnyRequest()
325 * and \a CActiveScheduler::RunIfReady(). If the timeout value is
326 * specified, this function will schedule a timer entry to the timer
327 * heap (which is an Active Object), to limit the wait time for event
328 * occurences. Scheduling a timer entry is an expensive operation,
329 * therefore application should only specify a timeout value when it's
330 * really necessary (for example, when it's not sure there are other
331 * Active Objects currently running in the application).
332 *
333 * @param priority The minimum priority of the Active Objects to
334 * poll, which values are from CActive::TPriority
335 * constants. If -1 is given, CActive::EPriorityStandard.
336 * priority will be used.
337 * @param ms_timeout Optional timeout to wait. Application should
338 * specify -1 to let the function wait indefinitely
339 * for any events.
340 *
341 * @return PJ_TRUE if there have been any events executed
342 * during the polling. This function will only return
343 * PJ_FALSE if \a ms_timeout argument is specified
344 * (i.e. the value is not -1) and there was no event
345 * executed when the timeout timer elapsed.
346 */
347PJ_DECL(pj_bool_t) pj_symbianos_poll(int priority, int ms_timeout);
348
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000349
350/**
351 * This structure declares Symbian OS specific parameters that can be
352 * specified when calling #pj_symbianos_set_params().
353 */
354typedef struct pj_symbianos_params
355{
356 /**
357 * Optional RSocketServ instance to be used by PJLIB. If this
358 * value is NULL, PJLIB will create a new RSocketServ instance
359 * when pj_init() is called.
360 */
361 void *rsocketserv;
362
363 /**
364 * Optional RConnection instance to be used by PJLIB when creating
365 * sockets. If this value is NULL, no RConnection will be
366 * specified when creating sockets.
367 */
368 void *rconnection;
369
370 /**
371 * Optional RHostResolver instance to be used by PJLIB. If this value
372 * is NULL, a new RHostResolver instance will be created when
373 * pj_init() is called.
374 */
375 void *rhostresolver;
376
Benny Prijono62b86eb2007-12-01 08:52:57 +0000377 /**
378 * Optional RHostResolver for IPv6 instance to be used by PJLIB.
379 * If this value is NULL, a new RHostResolver instance will be created
380 * when pj_init() is called.
381 */
382 void *rhostresolver6;
383
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000384} pj_symbianos_params;
385
386/**
387 * Specify Symbian OS parameters to be used by PJLIB. This function MUST
388 * be called before #pj_init() is called.
389 *
390 * @param prm Symbian specific parameters.
391 *
392 * @return PJ_SUCCESS if the parameters can be applied
393 * successfully.
394 */
395PJ_DECL(pj_status_t) pj_symbianos_set_params(pj_symbianos_params *prm);
396
397
Benny Prijono8ab968f2007-07-20 08:08:30 +0000398/**
399 * @}
400 */
401
402/* **************************************************************************/
403/**
Benny Prijono9033e312005-11-21 02:08:39 +0000404 * @defgroup PJ_TLS Thread Local Storage.
405 * @ingroup PJ_OS
406 * @{
407 */
408
409/**
410 * Allocate thread local storage index. The initial value of the variable at
411 * the index is zero.
412 *
413 * @param index Pointer to hold the return value.
414 * @return PJ_SUCCESS on success, or the error code.
415 */
416PJ_DECL(pj_status_t) pj_thread_local_alloc(long *index);
417
418/**
419 * Deallocate thread local variable.
420 *
421 * @param index The variable index.
422 */
423PJ_DECL(void) pj_thread_local_free(long index);
424
425/**
426 * Set the value of thread local variable.
427 *
428 * @param index The index of the variable.
429 * @param value The value.
430 */
431PJ_DECL(pj_status_t) pj_thread_local_set(long index, void *value);
432
433/**
434 * Get the value of thread local variable.
435 *
436 * @param index The index of the variable.
437 * @return The value.
438 */
439PJ_DECL(void*) pj_thread_local_get(long index);
440
441
442/**
443 * @}
444 */
445
446
Benny Prijono92ac4472006-07-22 13:42:56 +0000447/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000448/**
449 * @defgroup PJ_ATOMIC Atomic Variables
450 * @ingroup PJ_OS
451 * @{
452 *
453 * This module provides API to manipulate atomic variables.
454 *
455 * \section pj_atomic_examples_sec Examples
456 *
457 * For some example codes, please see:
458 * - @ref page_pjlib_atomic_test
459 */
460
461
462/**
463 * Create atomic variable.
464 *
465 * @param pool The pool.
466 * @param initial The initial value of the atomic variable.
467 * @param atomic Pointer to hold the atomic variable upon return.
468 *
469 * @return PJ_SUCCESS on success, or the error code.
470 */
471PJ_DECL(pj_status_t) pj_atomic_create( pj_pool_t *pool,
472 pj_atomic_value_t initial,
473 pj_atomic_t **atomic );
474
475/**
476 * Destroy atomic variable.
477 *
478 * @param atomic_var the atomic variable.
479 *
480 * @return PJ_SUCCESS if success.
481 */
482PJ_DECL(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var );
483
484/**
485 * Set the value of an atomic type, and return the previous value.
486 *
487 * @param atomic_var the atomic variable.
488 * @param value value to be set to the variable.
489 */
490PJ_DECL(void) pj_atomic_set( pj_atomic_t *atomic_var,
491 pj_atomic_value_t value);
492
493/**
494 * Get the value of an atomic type.
495 *
496 * @param atomic_var the atomic variable.
497 *
498 * @return the value of the atomic variable.
499 */
500PJ_DECL(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var);
501
502/**
503 * Increment the value of an atomic type.
504 *
505 * @param atomic_var the atomic variable.
506 */
507PJ_DECL(void) pj_atomic_inc(pj_atomic_t *atomic_var);
508
509/**
510 * Increment the value of an atomic type and get the result.
511 *
512 * @param atomic_var the atomic variable.
513 *
514 * @return The incremented value.
515 */
516PJ_DECL(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var);
517
518/**
519 * Decrement the value of an atomic type.
520 *
521 * @param atomic_var the atomic variable.
522 */
523PJ_DECL(void) pj_atomic_dec(pj_atomic_t *atomic_var);
524
525/**
526 * Decrement the value of an atomic type and get the result.
527 *
528 * @param atomic_var the atomic variable.
529 *
530 * @return The decremented value.
531 */
532PJ_DECL(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var);
533
534/**
535 * Add a value to an atomic type.
536 *
537 * @param atomic_var The atomic variable.
538 * @param value Value to be added.
539 */
540PJ_DECL(void) pj_atomic_add( pj_atomic_t *atomic_var,
541 pj_atomic_value_t value);
542
543/**
544 * Add a value to an atomic type and get the result.
545 *
546 * @param atomic_var The atomic variable.
547 * @param value Value to be added.
548 *
549 * @return The result after the addition.
550 */
551PJ_DECL(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
552 pj_atomic_value_t value);
553
554/**
555 * @}
556 */
557
Benny Prijono92ac4472006-07-22 13:42:56 +0000558/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000559/**
560 * @defgroup PJ_MUTEX Mutexes.
561 * @ingroup PJ_OS
562 * @{
563 *
564 * Mutex manipulation. Alternatively, application can use higher abstraction
565 * for lock objects, which provides uniform API for all kinds of lock
566 * mechanisms, including mutex. See @ref PJ_LOCK for more information.
567 */
568
569/**
570 * Mutex types:
571 * - PJ_MUTEX_DEFAULT: default mutex type, which is system dependent.
572 * - PJ_MUTEX_SIMPLE: non-recursive mutex.
Benny Prijono8ab968f2007-07-20 08:08:30 +0000573 * - PJ_MUTEX_RECURSE: recursive mutex.
Benny Prijono9033e312005-11-21 02:08:39 +0000574 */
575typedef enum pj_mutex_type_e
576{
577 PJ_MUTEX_DEFAULT,
578 PJ_MUTEX_SIMPLE,
Benny Prijono92ac4472006-07-22 13:42:56 +0000579 PJ_MUTEX_RECURSE
Benny Prijono9033e312005-11-21 02:08:39 +0000580} pj_mutex_type_e;
581
582
583/**
584 * Create mutex of the specified type.
585 *
586 * @param pool The pool.
587 * @param name Name to be associated with the mutex (for debugging).
588 * @param type The type of the mutex, of type #pj_mutex_type_e.
589 * @param mutex Pointer to hold the returned mutex instance.
590 *
591 * @return PJ_SUCCESS on success, or the error code.
592 */
593PJ_DECL(pj_status_t) pj_mutex_create(pj_pool_t *pool,
594 const char *name,
595 int type,
596 pj_mutex_t **mutex);
597
598/**
599 * Create simple, non-recursive mutex.
600 * This function is a simple wrapper for #pj_mutex_create to create
601 * non-recursive mutex.
602 *
603 * @param pool The pool.
604 * @param name Mutex name.
605 * @param mutex Pointer to hold the returned mutex instance.
606 *
607 * @return PJ_SUCCESS on success, or the error code.
608 */
609PJ_DECL(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,
610 pj_mutex_t **mutex );
611
612/**
613 * Create recursive mutex.
614 * This function is a simple wrapper for #pj_mutex_create to create
615 * recursive mutex.
616 *
617 * @param pool The pool.
618 * @param name Mutex name.
619 * @param mutex Pointer to hold the returned mutex instance.
620 *
621 * @return PJ_SUCCESS on success, or the error code.
622 */
623PJ_DECL(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
624 const char *name,
625 pj_mutex_t **mutex );
626
627/**
628 * Acquire mutex lock.
629 *
630 * @param mutex The mutex.
631 * @return PJ_SUCCESS on success, or the error code.
632 */
633PJ_DECL(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex);
634
635/**
636 * Release mutex lock.
637 *
638 * @param mutex The mutex.
639 * @return PJ_SUCCESS on success, or the error code.
640 */
641PJ_DECL(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex);
642
643/**
644 * Try to acquire mutex lock.
645 *
646 * @param mutex The mutex.
647 * @return PJ_SUCCESS on success, or the error code if the
648 * lock couldn't be acquired.
649 */
650PJ_DECL(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex);
651
652/**
653 * Destroy mutex.
654 *
655 * @param mutex Te mutex.
656 * @return PJ_SUCCESS on success, or the error code.
657 */
658PJ_DECL(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex);
659
660/**
661 * Determine whether calling thread is owning the mutex (only available when
662 * PJ_DEBUG is set).
663 * @param mutex The mutex.
664 * @return Non-zero if yes.
665 */
666#if defined(PJ_DEBUG) && PJ_DEBUG != 0
667 PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);
668#else
669# define pj_mutex_is_locked(mutex) 1
670#endif
671
672/**
673 * @}
674 */
675
Benny Prijono92ac4472006-07-22 13:42:56 +0000676/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000677/**
Benny Prijono0ca04b62005-12-30 23:50:15 +0000678 * @defgroup PJ_RW_MUTEX Reader/Writer Mutex
679 * @ingroup PJ_OS
680 * @{
681 * Reader/writer mutex is a classic synchronization object where multiple
682 * readers can acquire the mutex, but only a single writer can acquire the
683 * mutex.
684 */
Benny Prijono294c2532006-06-16 16:52:51 +0000685
686/**
687 * Opaque declaration for reader/writer mutex.
688 * Reader/writer mutex is a classic synchronization object where multiple
689 * readers can acquire the mutex, but only a single writer can acquire the
690 * mutex.
691 */
Benny Prijono0ca04b62005-12-30 23:50:15 +0000692typedef struct pj_rwmutex_t pj_rwmutex_t;
693
694/**
695 * Create reader/writer mutex.
696 *
697 * @param pool Pool to allocate memory for the mutex.
698 * @param name Name to be assigned to the mutex.
699 * @param mutex Pointer to receive the newly created mutex.
700 *
701 * @return PJ_SUCCESS on success, or the error code.
702 */
703PJ_DECL(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
704 pj_rwmutex_t **mutex);
705
706/**
707 * Lock the mutex for reading.
708 *
709 * @param mutex The mutex.
710 * @return PJ_SUCCESS on success, or the error code.
711 */
712PJ_DECL(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex);
713
714/**
715 * Lock the mutex for writing.
716 *
717 * @param mutex The mutex.
718 * @return PJ_SUCCESS on success, or the error code.
719 */
720PJ_DECL(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex);
721
722/**
723 * Release read lock.
724 *
725 * @param mutex The mutex.
726 * @return PJ_SUCCESS on success, or the error code.
727 */
728PJ_DECL(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex);
729
730/**
731 * Release write lock.
732 *
733 * @param mutex The mutex.
734 * @return PJ_SUCCESS on success, or the error code.
735 */
736PJ_DECL(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex);
737
738/**
739 * Destroy reader/writer mutex.
740 *
741 * @param mutex The mutex.
742 * @return PJ_SUCCESS on success, or the error code.
743 */
744PJ_DECL(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex);
745
746
747/**
748 * @}
749 */
750
751
Benny Prijono92ac4472006-07-22 13:42:56 +0000752/* **************************************************************************/
Benny Prijono0ca04b62005-12-30 23:50:15 +0000753/**
Benny Prijono9033e312005-11-21 02:08:39 +0000754 * @defgroup PJ_CRIT_SEC Critical sections.
755 * @ingroup PJ_OS
756 * @{
757 * Critical section protection can be used to protect regions where:
758 * - mutual exclusion protection is needed.
759 * - it's rather too expensive to create a mutex.
760 * - the time spent in the region is very very brief.
761 *
762 * Critical section is a global object, and it prevents any threads from
763 * entering any regions that are protected by critical section once a thread
764 * is already in the section.
765 *
766 * Critial section is \a not recursive!
767 *
768 * Application <b>MUST NOT</b> call any functions that may cause current
769 * thread to block (such as allocating memory, performing I/O, locking mutex,
770 * etc.) while holding the critical section.
771 */
772/**
773 * Enter critical section.
774 */
775PJ_DECL(void) pj_enter_critical_section(void);
776
777/**
778 * Leave critical section.
779 */
780PJ_DECL(void) pj_leave_critical_section(void);
781
782/**
783 * @}
784 */
785
Benny Prijono92ac4472006-07-22 13:42:56 +0000786/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000787#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
788/**
789 * @defgroup PJ_SEM Semaphores.
790 * @ingroup PJ_OS
791 * @{
792 *
793 * This module provides abstraction for semaphores, where available.
794 */
795
796/**
797 * Create semaphore.
798 *
799 * @param pool The pool.
800 * @param name Name to be assigned to the semaphore (for logging purpose)
801 * @param initial The initial count of the semaphore.
802 * @param max The maximum count of the semaphore.
803 * @param sem Pointer to hold the semaphore created.
804 *
805 * @return PJ_SUCCESS on success, or the error code.
806 */
807PJ_DECL(pj_status_t) pj_sem_create( pj_pool_t *pool,
808 const char *name,
809 unsigned initial,
810 unsigned max,
811 pj_sem_t **sem);
812
813/**
814 * Wait for semaphore.
815 *
816 * @param sem The semaphore.
817 *
818 * @return PJ_SUCCESS on success, or the error code.
819 */
820PJ_DECL(pj_status_t) pj_sem_wait(pj_sem_t *sem);
821
822/**
823 * Try wait for semaphore.
824 *
825 * @param sem The semaphore.
826 *
827 * @return PJ_SUCCESS on success, or the error code.
828 */
829PJ_DECL(pj_status_t) pj_sem_trywait(pj_sem_t *sem);
830
831/**
832 * Release semaphore.
833 *
834 * @param sem The semaphore.
835 *
836 * @return PJ_SUCCESS on success, or the error code.
837 */
838PJ_DECL(pj_status_t) pj_sem_post(pj_sem_t *sem);
839
840/**
841 * Destroy semaphore.
842 *
843 * @param sem The semaphore.
844 *
845 * @return PJ_SUCCESS on success, or the error code.
846 */
847PJ_DECL(pj_status_t) pj_sem_destroy(pj_sem_t *sem);
848
849/**
850 * @}
851 */
852#endif /* PJ_HAS_SEMAPHORE */
853
854
Benny Prijono92ac4472006-07-22 13:42:56 +0000855/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000856#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
857/**
858 * @defgroup PJ_EVENT Event Object.
859 * @ingroup PJ_OS
860 * @{
861 *
862 * This module provides abstraction to event object (e.g. Win32 Event) where
863 * available. Event objects can be used for synchronization among threads.
864 */
865
866/**
867 * Create event object.
868 *
869 * @param pool The pool.
870 * @param name The name of the event object (for logging purpose).
871 * @param manual_reset Specify whether the event is manual-reset
872 * @param initial Specify the initial state of the event object.
873 * @param event Pointer to hold the returned event object.
874 *
875 * @return event handle, or NULL if failed.
876 */
877PJ_DECL(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name,
878 pj_bool_t manual_reset, pj_bool_t initial,
879 pj_event_t **event);
880
881/**
882 * Wait for event to be signaled.
883 *
884 * @param event The event object.
885 *
886 * @return zero if successfull.
887 */
888PJ_DECL(pj_status_t) pj_event_wait(pj_event_t *event);
889
890/**
891 * Try wait for event object to be signalled.
892 *
893 * @param event The event object.
894 *
895 * @return zero if successfull.
896 */
897PJ_DECL(pj_status_t) pj_event_trywait(pj_event_t *event);
898
899/**
900 * Set the event object state to signaled. For auto-reset event, this
901 * will only release the first thread that are waiting on the event. For
902 * manual reset event, the state remains signaled until the event is reset.
903 * If there is no thread waiting on the event, the event object state
904 * remains signaled.
905 *
906 * @param event The event object.
907 *
908 * @return zero if successfull.
909 */
910PJ_DECL(pj_status_t) pj_event_set(pj_event_t *event);
911
912/**
913 * Set the event object to signaled state to release appropriate number of
914 * waiting threads and then reset the event object to non-signaled. For
915 * manual-reset event, this function will release all waiting threads. For
916 * auto-reset event, this function will only release one waiting thread.
917 *
918 * @param event The event object.
919 *
920 * @return zero if successfull.
921 */
922PJ_DECL(pj_status_t) pj_event_pulse(pj_event_t *event);
923
924/**
925 * Set the event object state to non-signaled.
926 *
927 * @param event The event object.
928 *
929 * @return zero if successfull.
930 */
931PJ_DECL(pj_status_t) pj_event_reset(pj_event_t *event);
932
933/**
934 * Destroy the event object.
935 *
936 * @param event The event object.
937 *
938 * @return zero if successfull.
939 */
940PJ_DECL(pj_status_t) pj_event_destroy(pj_event_t *event);
941
942/**
943 * @}
944 */
945#endif /* PJ_HAS_EVENT_OBJ */
946
Benny Prijono92ac4472006-07-22 13:42:56 +0000947/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000948/**
949 * @addtogroup PJ_TIME Time Data Type and Manipulation.
950 * @ingroup PJ_OS
951 * @{
952 * This module provides API for manipulating time.
953 *
954 * \section pj_time_examples_sec Examples
955 *
956 * For examples, please see:
957 * - \ref page_pjlib_sleep_test
958 */
959
960/**
961 * Get current time of day in local representation.
962 *
963 * @param tv Variable to store the result.
964 *
965 * @return zero if successfull.
966 */
967PJ_DECL(pj_status_t) pj_gettimeofday(pj_time_val *tv);
968
969
970/**
971 * Parse time value into date/time representation.
972 *
973 * @param tv The time.
974 * @param pt Variable to store the date time result.
975 *
976 * @return zero if successfull.
977 */
978PJ_DECL(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt);
979
980/**
981 * Encode date/time to time value.
982 *
983 * @param pt The date/time.
984 * @param tv Variable to store time value result.
985 *
986 * @return zero if successfull.
987 */
988PJ_DECL(pj_status_t) pj_time_encode(const pj_parsed_time *pt, pj_time_val *tv);
989
990/**
991 * Convert local time to GMT.
992 *
993 * @param tv Time to convert.
994 *
995 * @return zero if successfull.
996 */
997PJ_DECL(pj_status_t) pj_time_local_to_gmt(pj_time_val *tv);
998
999/**
1000 * Convert GMT to local time.
1001 *
1002 * @param tv Time to convert.
1003 *
1004 * @return zero if successfull.
1005 */
1006PJ_DECL(pj_status_t) pj_time_gmt_to_local(pj_time_val *tv);
1007
1008/**
1009 * @}
1010 */
1011
Benny Prijono92ac4472006-07-22 13:42:56 +00001012/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +00001013#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0
1014
1015/**
1016 * @defgroup PJ_TERM Terminal
1017 * @ingroup PJ_OS
1018 * @{
1019 */
1020
1021/**
1022 * Set current terminal color.
1023 *
1024 * @param color The RGB color.
1025 *
1026 * @return zero on success.
1027 */
1028PJ_DECL(pj_status_t) pj_term_set_color(pj_color_t color);
1029
1030/**
1031 * Get current terminal foreground color.
1032 *
1033 * @return RGB color.
1034 */
1035PJ_DECL(pj_color_t) pj_term_get_color(void);
1036
1037/**
1038 * @}
1039 */
1040
1041#endif /* PJ_TERM_HAS_COLOR */
1042
Benny Prijono92ac4472006-07-22 13:42:56 +00001043/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +00001044/**
1045 * @defgroup PJ_TIMESTAMP High Resolution Timestamp
1046 * @ingroup PJ_OS
1047 * @{
1048 *
1049 * PJLIB provides <b>High Resolution Timestamp</b> API to access highest
1050 * resolution timestamp value provided by the platform. The API is usefull
1051 * to measure precise elapsed time, and can be used in applications such
1052 * as profiling.
1053 *
1054 * The timestamp value is represented in cycles, and can be related to
1055 * normal time (in seconds or sub-seconds) using various functions provided.
1056 *
1057 * \section pj_timestamp_examples_sec Examples
1058 *
1059 * For examples, please see:
1060 * - \ref page_pjlib_sleep_test
1061 * - \ref page_pjlib_timestamp_test
1062 */
1063
1064/*
1065 * High resolution timer.
1066 */
1067#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
1068
1069/**
Benny Prijono9033e312005-11-21 02:08:39 +00001070 * Acquire high resolution timer value. The time value are stored
1071 * in cycles.
1072 *
1073 * @param ts High resolution timer value.
1074 * @return PJ_SUCCESS or the appropriate error code.
1075 *
1076 * @see pj_get_timestamp_freq().
1077 */
1078PJ_DECL(pj_status_t) pj_get_timestamp(pj_timestamp *ts);
1079
1080/**
1081 * Get high resolution timer frequency, in cycles per second.
1082 *
1083 * @param freq Timer frequency, in cycles per second.
1084 * @return PJ_SUCCESS or the appropriate error code.
1085 */
1086PJ_DECL(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq);
1087
1088/**
Benny Prijonoc357d642007-01-20 05:14:24 +00001089 * Set timestamp from 32bit values.
1090 * @param t The timestamp to be set.
1091 * @param hi The high 32bit part.
1092 * @param lo The low 32bit part.
1093 */
1094PJ_INLINE(void) pj_set_timestamp32(pj_timestamp *t, pj_uint32_t hi,
1095 pj_uint32_t lo)
1096{
1097 t->u32.hi = hi;
1098 t->u32.lo = lo;
1099}
1100
Benny Prijono6f86e7c2007-04-02 11:28:41 +00001101
1102/**
1103 * Compare timestamp t1 and t2.
1104 * @param t1 t1.
1105 * @param t2 t2.
1106 * @return -1 if (t1 < t2), 1 if (t1 > t2), or 0 if (t1 == t2)
1107 */
1108PJ_INLINE(int) pj_cmp_timestamp(const pj_timestamp *t1, const pj_timestamp *t2)
1109{
1110#if PJ_HAS_INT64
1111 if (t1->u64 < t2->u64)
1112 return -1;
1113 else if (t1->u64 > t2->u64)
1114 return 1;
1115 else
1116 return 0;
1117#else
1118 if (t1->u32.hi < t2->u32.hi ||
1119 (t1->u32.hi == t2->u32.hi && t1->u32.lo < t2->u32.lo))
1120 return -1;
1121 else if (t1->u32.hi > t2->u32.hi ||
1122 (t1->u32.hi == t2->u32.hi && t1->u32.lo > t2->u32.lo))
1123 return 1;
1124 else
1125 return 0;
1126#endif
1127}
1128
1129
Benny Prijonoc357d642007-01-20 05:14:24 +00001130/**
Benny Prijono9033e312005-11-21 02:08:39 +00001131 * Add timestamp t2 to t1.
1132 * @param t1 t1.
1133 * @param t2 t2.
1134 */
1135PJ_INLINE(void) pj_add_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
1136{
1137#if PJ_HAS_INT64
1138 t1->u64 += t2->u64;
1139#else
1140 pj_uint32_t old = t1->u32.lo;
1141 t1->u32.hi += t2->u32.hi;
1142 t1->u32.lo += t2->u32.lo;
1143 if (t1->u32.lo < old)
1144 ++t1->u32.hi;
1145#endif
1146}
1147
1148/**
Benny Prijonoc357d642007-01-20 05:14:24 +00001149 * Add timestamp t2 to t1.
1150 * @param t1 t1.
1151 * @param t2 t2.
1152 */
1153PJ_INLINE(void) pj_add_timestamp32(pj_timestamp *t1, pj_uint32_t t2)
1154{
1155#if PJ_HAS_INT64
1156 t1->u64 += t2;
1157#else
1158 pj_uint32_t old = t1->u32.lo;
1159 t1->u32.lo += t2;
1160 if (t1->u32.lo < old)
1161 ++t1->u32.hi;
1162#endif
1163}
1164
1165/**
Benny Prijono9033e312005-11-21 02:08:39 +00001166 * Substract timestamp t2 from t1.
1167 * @param t1 t1.
1168 * @param t2 t2.
1169 */
1170PJ_INLINE(void) pj_sub_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
1171{
1172#if PJ_HAS_INT64
1173 t1->u64 -= t2->u64;
1174#else
1175 t1->u32.hi -= t2->u32.hi;
1176 if (t1->u32.lo >= t2->u32.lo)
1177 t1->u32.lo -= t2->u32.lo;
1178 else {
1179 t1->u32.lo -= t2->u32.lo;
1180 --t1->u32.hi;
1181 }
1182#endif
1183}
1184
1185/**
Benny Prijonoc357d642007-01-20 05:14:24 +00001186 * Substract timestamp t2 from t1.
1187 * @param t1 t1.
1188 * @param t2 t2.
1189 */
1190PJ_INLINE(void) pj_sub_timestamp32(pj_timestamp *t1, pj_uint32_t t2)
1191{
1192#if PJ_HAS_INT64
1193 t1->u64 -= t2;
1194#else
1195 if (t1->u32.lo >= t2)
1196 t1->u32.lo -= t2;
1197 else {
1198 t1->u32.lo -= t2;
1199 --t1->u32.hi;
1200 }
1201#endif
1202}
1203
1204/**
1205 * Get the timestamp difference between t2 and t1 (that is t2 minus t1),
1206 * and return a 32bit signed integer difference.
1207 */
1208PJ_INLINE(pj_int32_t) pj_timestamp_diff32(const pj_timestamp *t1,
1209 const pj_timestamp *t2)
1210{
1211 /* Be careful with the signess (I think!) */
1212#if PJ_HAS_INT64
1213 pj_int64_t diff = t2->u64 - t1->u64;
1214 return (pj_int32_t) diff;
1215#else
1216 pj_int32 diff = t2->u32.lo - t1->u32.lo;
1217 return diff;
1218#endif
1219}
1220
1221
1222/**
Benny Prijono9033e312005-11-21 02:08:39 +00001223 * Calculate the elapsed time, and store it in pj_time_val.
1224 * This function calculates the elapsed time using highest precision
1225 * calculation that is available for current platform, considering
1226 * whether floating point or 64-bit precision arithmetic is available.
1227 * For maximum portability, application should prefer to use this function
1228 * rather than calculating the elapsed time by itself.
1229 *
1230 * @param start The starting timestamp.
1231 * @param stop The end timestamp.
1232 *
1233 * @return Elapsed time as #pj_time_val.
1234 *
1235 * @see pj_elapsed_usec(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1236 */
1237PJ_DECL(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
1238 const pj_timestamp *stop );
1239
1240/**
Benny Prijono99683ae2005-11-21 16:59:47 +00001241 * Calculate the elapsed time as 32-bit miliseconds.
1242 * This function calculates the elapsed time using highest precision
1243 * calculation that is available for current platform, considering
1244 * whether floating point or 64-bit precision arithmetic is available.
1245 * For maximum portability, application should prefer to use this function
1246 * rather than calculating the elapsed time by itself.
1247 *
1248 * @param start The starting timestamp.
1249 * @param stop The end timestamp.
1250 *
1251 * @return Elapsed time in milisecond.
1252 *
1253 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1254 */
1255PJ_DECL(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
1256 const pj_timestamp *stop );
1257
1258/**
Benny Prijono9033e312005-11-21 02:08:39 +00001259 * Calculate the elapsed time in 32-bit microseconds.
1260 * This function calculates the elapsed time using highest precision
1261 * calculation that is available for current platform, considering
1262 * whether floating point or 64-bit precision arithmetic is available.
1263 * For maximum portability, application should prefer to use this function
1264 * rather than calculating the elapsed time by itself.
1265 *
1266 * @param start The starting timestamp.
1267 * @param stop The end timestamp.
1268 *
1269 * @return Elapsed time in microsecond.
1270 *
1271 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1272 */
1273PJ_DECL(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
1274 const pj_timestamp *stop );
1275
1276/**
1277 * Calculate the elapsed time in 32-bit nanoseconds.
1278 * This function calculates the elapsed time using highest precision
1279 * calculation that is available for current platform, considering
1280 * whether floating point or 64-bit precision arithmetic is available.
1281 * For maximum portability, application should prefer to use this function
1282 * rather than calculating the elapsed time by itself.
1283 *
1284 * @param start The starting timestamp.
1285 * @param stop The end timestamp.
1286 *
1287 * @return Elapsed time in nanoseconds.
1288 *
1289 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_usec()
1290 */
1291PJ_DECL(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
1292 const pj_timestamp *stop );
1293
1294/**
1295 * Calculate the elapsed time in 32-bit cycles.
1296 * This function calculates the elapsed time using highest precision
1297 * calculation that is available for current platform, considering
1298 * whether floating point or 64-bit precision arithmetic is available.
1299 * For maximum portability, application should prefer to use this function
1300 * rather than calculating the elapsed time by itself.
1301 *
1302 * @param start The starting timestamp.
1303 * @param stop The end timestamp.
1304 *
1305 * @return Elapsed time in cycles.
1306 *
1307 * @see pj_elapsed_usec(), pj_elapsed_time(), pj_elapsed_nanosec()
1308 */
1309PJ_DECL(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
1310 const pj_timestamp *stop );
1311
1312
1313#endif /* PJ_HAS_HIGH_RES_TIMER */
1314
1315/** @} */
1316
1317
Benny Prijono92ac4472006-07-22 13:42:56 +00001318/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +00001319/**
1320 * Internal PJLIB function to initialize the threading subsystem.
1321 * @return PJ_SUCCESS or the appropriate error code.
1322 */
1323pj_status_t pj_thread_init(void);
1324
1325
1326PJ_END_DECL
1327
1328#endif /* __PJ_OS_H__ */
1329