1 /*****************************************************************************
2 * threads.c : threads implementation for the VideoLAN client
3 *****************************************************************************
4 * Copyright (C) 1999-2008 the VideoLAN team
7 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8 * Samuel Hocevar <sam@zoy.org>
9 * Gildas Bazin <gbazin@netcourrier.com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
32 #include <vlc_common.h>
40 #if defined( LIBVLC_USE_PTHREAD )
45 struct vlc_thread_boot
47 void * (*entry) (vlc_object_t *);
51 static void *thread_entry (void *data)
53 vlc_object_t *obj = ((struct vlc_thread_boot *)data)->object;
54 void *(*func) (vlc_object_t *) = ((struct vlc_thread_boot *)data)->entry;
57 msg_Dbg (obj, "thread started");
59 msg_Dbg (obj, "thread ended");
64 #undef vlc_thread_create
65 /*****************************************************************************
66 * vlc_thread_create: create a thread
67 *****************************************************************************
68 * Note that i_priority is only taken into account on platforms supporting
69 * userland real-time priority threads.
70 *****************************************************************************/
71 int vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line,
72 const char *psz_name, void *(*func) ( vlc_object_t * ),
76 vlc_object_internals_t *p_priv = vlc_internals( p_this );
78 struct vlc_thread_boot *boot = malloc (sizeof (*boot));
82 boot->object = p_this;
84 /* Make sure we don't re-create a thread if the object has already one */
85 assert( !p_priv->b_thread );
87 #if defined( LIBVLC_USE_PTHREAD )
89 if( config_GetInt( p_this, "rt-priority" ) > 0 )
92 /* Hack to avoid error msg */
93 if( config_GetType( p_this, "rt-offset" ) )
94 i_priority += config_GetInt( p_this, "rt-offset" );
98 p_priv->b_thread = true;
99 i_ret = vlc_clone( &p_priv->thread_id, thread_entry, boot, i_priority );
101 msg_Dbg( p_this, "thread (%s) created at priority %d (%s:%d)",
102 psz_name, i_priority, psz_file, i_line );
105 p_priv->b_thread = false;
107 msg_Err( p_this, "%s thread could not be created at %s:%d (%m)",
108 psz_name, psz_file, i_line );
114 /*****************************************************************************
115 * vlc_thread_set_priority: set the priority of the current thread when we
116 * couldn't set it in vlc_thread_create (for instance for the main thread)
117 *****************************************************************************/
118 int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file,
119 int i_line, int i_priority )
121 vlc_object_internals_t *p_priv = vlc_internals( p_this );
123 if( !p_priv->b_thread )
125 msg_Err( p_this, "couldn't set priority of non-existent thread" );
129 #if defined( LIBVLC_USE_PTHREAD )
131 if( config_GetInt( p_this, "rt-priority" ) > 0 )
134 int i_error, i_policy;
135 struct sched_param param;
137 memset( ¶m, 0, sizeof(struct sched_param) );
138 if( config_GetType( p_this, "rt-offset" ) )
139 i_priority += config_GetInt( p_this, "rt-offset" );
140 if( i_priority <= 0 )
142 param.sched_priority = (-1) * i_priority;
143 i_policy = SCHED_OTHER;
147 param.sched_priority = i_priority;
150 if( (i_error = pthread_setschedparam( p_priv->thread_id,
151 i_policy, ¶m )) )
154 msg_Warn( p_this, "couldn't set thread priority (%s:%d): %m",
160 #elif defined( WIN32 ) || defined( UNDER_CE )
161 VLC_UNUSED( psz_file); VLC_UNUSED( i_line );
163 if( !SetThreadPriority(p_priv->thread_id->handle, i_priority) )
165 msg_Warn( p_this, "couldn't set a faster priority" );
174 /*****************************************************************************
175 * vlc_thread_join: wait until a thread exits, inner version
176 *****************************************************************************/
177 void __vlc_thread_join( vlc_object_t *p_this )
179 vlc_object_internals_t *p_priv = vlc_internals( p_this );
181 #if defined( LIBVLC_USE_PTHREAD )
182 vlc_join (p_priv->thread_id, NULL);
184 #elif defined( UNDER_CE ) || defined( WIN32 )
186 FILETIME create_ft, exit_ft, kernel_ft, user_ft;
187 int64_t real_time, kernel_time, user_time;
190 if( ! DuplicateHandle(GetCurrentProcess(),
191 p_priv->thread_id->handle,
196 DUPLICATE_SAME_ACCESS) )
198 p_priv->b_thread = false;
199 return; /* We have a problem! */
202 hThread = p_priv->thread_id->handle;
205 vlc_join( p_priv->thread_id, NULL );
207 if( GetThreadTimes( hThread, &create_ft, &exit_ft, &kernel_ft, &user_ft ) )
210 ((((int64_t)exit_ft.dwHighDateTime)<<32)| exit_ft.dwLowDateTime) -
211 ((((int64_t)create_ft.dwHighDateTime)<<32)| create_ft.dwLowDateTime);
215 ((((int64_t)kernel_ft.dwHighDateTime)<<32)|
216 kernel_ft.dwLowDateTime) / 10;
219 ((((int64_t)user_ft.dwHighDateTime)<<32)|
220 user_ft.dwLowDateTime) / 10;
222 msg_Dbg( p_this, "thread times: "
223 "real %"PRId64"m%fs, kernel %"PRId64"m%fs, user %"PRId64"m%fs",
224 real_time/60/1000000,
225 (double)((real_time%(60*1000000))/1000000.0),
226 kernel_time/60/1000000,
227 (double)((kernel_time%(60*1000000))/1000000.0),
228 user_time/60/1000000,
229 (double)((user_time%(60*1000000))/1000000.0) );
231 CloseHandle( hThread );
234 vlc_join( p_priv->thread_id, NULL );
238 p_priv->b_thread = false;
241 void vlc_thread_cancel (vlc_object_t *obj)
243 vlc_object_internals_t *priv = vlc_internals (obj);
246 vlc_cancel (priv->thread_id);