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