~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjlib/src/pjlib-test/thread.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: thread.c 3553 2011-05-05 06:14:19Z nanang $ */
2
 
/*
3
 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
 
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
 */
20
 
#include "test.h"
21
 
 
22
 
/**
23
 
 * \page page_pjlib_thread_test Test: Thread Test
24
 
 *
25
 
 * This file contains \a thread_test() definition.
26
 
 *
27
 
 * \section thread_test_scope_sec Scope of Test
28
 
 * This tests:
29
 
 *  - whether PJ_THREAD_SUSPENDED flag works.
30
 
 *  - whether multithreading works.
31
 
 *  - whether thread timeslicing works, and threads have equal
32
 
 *    time-slice proportion.
33
 
 *
34
 
 * APIs tested:
35
 
 *  - pj_thread_create()
36
 
 *  - pj_thread_register()
37
 
 *  - pj_thread_this()
38
 
 *  - pj_thread_get_name()
39
 
 *  - pj_thread_destroy()
40
 
 *  - pj_thread_resume()
41
 
 *  - pj_thread_sleep()
42
 
 *  - pj_thread_join()
43
 
 *  - pj_thread_destroy()
44
 
 *
45
 
 *
46
 
 * This file is <b>pjlib-test/thread.c</b>
47
 
 *
48
 
 * \include pjlib-test/thread.c
49
 
 */
50
 
#if INCLUDE_THREAD_TEST
51
 
 
52
 
#include <pjlib.h>
53
 
 
54
 
#define THIS_FILE   "thread_test"
55
 
 
56
 
static volatile int quit_flag=0;
57
 
 
58
 
#if 0
59
 
#   define TRACE__(args)        PJ_LOG(3,args)
60
 
#else
61
 
#   define TRACE__(args)
62
 
#endif
63
 
 
64
 
 
65
 
/*
66
 
 * The thread's entry point.
67
 
 *
68
 
 * Each of the thread mainly will just execute the loop which
69
 
 * increments a variable.
70
 
 */
71
 
static void* thread_proc(pj_uint32_t *pcounter)
72
 
{
73
 
    /* Test that pj_thread_register() works. */
74
 
    pj_thread_desc desc;
75
 
    pj_thread_t *this_thread;
76
 
    unsigned id;
77
 
    pj_status_t rc;
78
 
 
79
 
    id = *pcounter;
80
 
    TRACE__((THIS_FILE, "     thread %d running..", id));
81
 
 
82
 
    pj_bzero(desc, sizeof(desc));
83
 
 
84
 
    rc = pj_thread_register("thread", desc, &this_thread);
85
 
    if (rc != PJ_SUCCESS) {
86
 
        app_perror("...error in pj_thread_register", rc);
87
 
        return NULL;
88
 
    }
89
 
 
90
 
    /* Test that pj_thread_this() works */
91
 
    this_thread = pj_thread_this();
92
 
    if (this_thread == NULL) {
93
 
        PJ_LOG(3,(THIS_FILE, "...error: pj_thread_this() returns NULL!"));
94
 
        return NULL;
95
 
    }
96
 
 
97
 
    /* Test that pj_thread_get_name() works */
98
 
    if (pj_thread_get_name(this_thread) == NULL) {
99
 
        PJ_LOG(3,(THIS_FILE, "...error: pj_thread_get_name() returns NULL!"));
100
 
        return NULL;
101
 
    }
102
 
 
103
 
    /* Main loop */
104
 
    for (;!quit_flag;) {
105
 
        (*pcounter)++;
106
 
        //Must sleep if platform doesn't do time-slicing.
107
 
        //pj_thread_sleep(0);
108
 
    }
109
 
 
110
 
    TRACE__((THIS_FILE, "     thread %d quitting..", id));
111
 
    return NULL;
112
 
}
113
 
 
114
 
/*
115
 
 * simple_thread()
116
 
 */
117
 
static int simple_thread(const char *title, unsigned flags)
118
 
{
119
 
    pj_pool_t *pool;
120
 
    pj_thread_t *thread;
121
 
    pj_status_t rc;
122
 
    pj_uint32_t counter = 0;
123
 
 
124
 
    PJ_LOG(3,(THIS_FILE, "..%s", title));
125
 
 
126
 
    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
127
 
    if (!pool)
128
 
        return -1000;
129
 
 
130
 
    quit_flag = 0;
131
 
 
132
 
    TRACE__((THIS_FILE, "    Creating thread 0.."));
133
 
    rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
134
 
                          &counter,
135
 
                          PJ_THREAD_DEFAULT_STACK_SIZE,
136
 
                          flags,
137
 
                          &thread);
138
 
 
139
 
    if (rc != PJ_SUCCESS) {
140
 
        app_perror("...error: unable to create thread", rc);
141
 
        return -1010;
142
 
    }
143
 
 
144
 
    TRACE__((THIS_FILE, "    Main thread waiting.."));
145
 
    pj_thread_sleep(1500);
146
 
    TRACE__((THIS_FILE, "    Main thread resuming.."));
147
 
 
148
 
    if (flags & PJ_THREAD_SUSPENDED) {
149
 
 
150
 
        /* Check that counter is still zero */
151
 
        if (counter != 0) {
152
 
            PJ_LOG(3,(THIS_FILE, "...error: thread is not suspended"));
153
 
            return -1015;
154
 
        }
155
 
 
156
 
        rc = pj_thread_resume(thread);
157
 
        if (rc != PJ_SUCCESS) {
158
 
            app_perror("...error: resume thread error", rc);
159
 
            return -1020;
160
 
        }
161
 
    }
162
 
 
163
 
    PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit.."));
164
 
 
165
 
    pj_thread_sleep(1500);
166
 
 
167
 
    quit_flag = 1;
168
 
    pj_thread_join(thread);
169
 
 
170
 
    pj_pool_release(pool);
171
 
 
172
 
    if (counter == 0) {
173
 
        PJ_LOG(3,(THIS_FILE, "...error: thread is not running"));
174
 
        return -1025;
175
 
    }
176
 
 
177
 
    PJ_LOG(3,(THIS_FILE, "...%s success", title));
178
 
    return PJ_SUCCESS;
179
 
}
180
 
 
181
 
 
182
 
/*
183
 
 * timeslice_test()
184
 
 */
185
 
static int timeslice_test(void)
186
 
{
187
 
    enum { NUM_THREADS = 4 };
188
 
    pj_pool_t *pool;
189
 
    pj_uint32_t counter[NUM_THREADS], lowest, highest, diff;
190
 
    pj_thread_t *thread[NUM_THREADS];
191
 
    unsigned i;
192
 
    pj_status_t rc;
193
 
 
194
 
    quit_flag = 0;
195
 
 
196
 
    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
197
 
    if (!pool)
198
 
        return -10;
199
 
 
200
 
    PJ_LOG(3,(THIS_FILE, "..timeslice testing with %d threads", NUM_THREADS));
201
 
 
202
 
    /* Create all threads in suspended mode. */
203
 
    for (i=0; i<NUM_THREADS; ++i) {
204
 
        counter[i] = i;
205
 
        rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
206
 
                              &counter[i],
207
 
                              PJ_THREAD_DEFAULT_STACK_SIZE,
208
 
                              PJ_THREAD_SUSPENDED,
209
 
                              &thread[i]);
210
 
        if (rc!=PJ_SUCCESS) {
211
 
            app_perror("...ERROR in pj_thread_create()", rc);
212
 
            return -20;
213
 
        }
214
 
    }
215
 
 
216
 
    /* Sleep for 1 second.
217
 
     * The purpose of this is to test whether all threads are suspended.
218
 
     */
219
 
    TRACE__((THIS_FILE, "    Main thread waiting.."));
220
 
    pj_thread_sleep(1000);
221
 
    TRACE__((THIS_FILE, "    Main thread resuming.."));
222
 
 
223
 
    /* Check that all counters are still zero. */
224
 
    for (i=0; i<NUM_THREADS; ++i) {
225
 
        if (counter[i] > i) {
226
 
            PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!",
227
 
                      i));
228
 
            return -30;
229
 
        }
230
 
    }
231
 
 
232
 
    /* Now resume all threads. */
233
 
    for (i=0; i<NUM_THREADS; ++i) {
234
 
        TRACE__((THIS_FILE, "    Resuming thread %d [%p]..", i, thread[i]));
235
 
        rc = pj_thread_resume(thread[i]);
236
 
        if (rc != PJ_SUCCESS) {
237
 
            app_perror("...ERROR in pj_thread_resume()", rc);
238
 
            return -40;
239
 
        }
240
 
    }
241
 
 
242
 
    /* Main thread sleeps for some time to allow threads to run.
243
 
     * The longer we sleep, the more accurate the calculation will be,
244
 
     * but it'll make user waits for longer for the test to finish.
245
 
     */
246
 
    TRACE__((THIS_FILE, "    Main thread waiting (5s).."));
247
 
    pj_thread_sleep(5000);
248
 
    TRACE__((THIS_FILE, "    Main thread resuming.."));
249
 
 
250
 
    /* Signal all threads to quit. */
251
 
    quit_flag = 1;
252
 
 
253
 
    /* Wait until all threads quit, then destroy. */
254
 
    for (i=0; i<NUM_THREADS; ++i) {
255
 
        TRACE__((THIS_FILE, "    Main thread joining thread %d [%p]..",
256
 
                            i, thread[i]));
257
 
        rc = pj_thread_join(thread[i]);
258
 
        if (rc != PJ_SUCCESS) {
259
 
            app_perror("...ERROR in pj_thread_join()", rc);
260
 
            return -50;
261
 
        }
262
 
        TRACE__((THIS_FILE, "    Destroying thread %d [%p]..", i, thread[i]));
263
 
        rc = pj_thread_destroy(thread[i]);
264
 
        if (rc != PJ_SUCCESS) {
265
 
            app_perror("...ERROR in pj_thread_destroy()", rc);
266
 
            return -60;
267
 
        }
268
 
    }
269
 
 
270
 
    TRACE__((THIS_FILE, "    Main thread calculating time slices.."));
271
 
 
272
 
    /* Now examine the value of the counters.
273
 
     * Check that all threads had equal proportion of processing.
274
 
     */
275
 
    lowest = 0xFFFFFFFF;
276
 
    highest = 0;
277
 
    for (i=0; i<NUM_THREADS; ++i) {
278
 
        if (counter[i] < lowest)
279
 
            lowest = counter[i];
280
 
        if (counter[i] > highest)
281
 
            highest = counter[i];
282
 
    }
283
 
 
284
 
    /* Check that all threads are running. */
285
 
    if (lowest < 2) {
286
 
        PJ_LOG(3,(THIS_FILE, "...ERROR: not all threads were running!"));
287
 
        return -70;
288
 
    }
289
 
 
290
 
    /* The difference between lowest and higest should be lower than 50%.
291
 
     */
292
 
    diff = (highest-lowest)*100 / ((highest+lowest)/2);
293
 
    if ( diff >= 50) {
294
 
        PJ_LOG(3,(THIS_FILE,
295
 
                  "...ERROR: thread didn't have equal timeslice!"));
296
 
        PJ_LOG(3,(THIS_FILE,
297
 
                  ".....lowest counter=%u, highest counter=%u, diff=%u%%",
298
 
                  lowest, highest, diff));
299
 
        return -80;
300
 
    } else {
301
 
        PJ_LOG(3,(THIS_FILE,
302
 
                  "...info: timeslice diff between lowest & highest=%u%%",
303
 
                  diff));
304
 
    }
305
 
 
306
 
    pj_pool_release(pool);
307
 
    return 0;
308
 
}
309
 
 
310
 
int thread_test(void)
311
 
{
312
 
    int rc;
313
 
 
314
 
    rc = simple_thread("simple thread test", 0);
315
 
    if (rc != PJ_SUCCESS)
316
 
        return rc;
317
 
 
318
 
    rc = simple_thread("suspended thread test", PJ_THREAD_SUSPENDED);
319
 
    if (rc != PJ_SUCCESS)
320
 
        return rc;
321
 
 
322
 
    rc = timeslice_test();
323
 
    if (rc != PJ_SUCCESS)
324
 
        return rc;
325
 
 
326
 
    return rc;
327
 
}
328
 
 
329
 
#else
330
 
/* To prevent warning about "translation unit is empty"
331
 
 * when this test is disabled.
332
 
 */
333
 
int dummy_thread_test;
334
 
#endif  /* INCLUDE_THREAD_TEST */