/*static*/ int
alsa_init(cubeb ** context, char const * context_name)
{
cubeb * ctx;
int r;
int i;
int fd[2];
pthread_attr_t attr;
snd_pcm_t * dummy;
assert(context);
*context = NULL;
pthread_mutex_lock(&cubeb_alsa_mutex);
if (!cubeb_alsa_error_handler_set) {
snd_lib_error_set_handler(silent_error_handler);
cubeb_alsa_error_handler_set = 1;
}
pthread_mutex_unlock(&cubeb_alsa_mutex);
ctx = calloc(1, sizeof(*ctx));
assert(ctx);
ctx->ops = &alsa_ops;
r = pthread_mutex_init(&ctx->mutex, NULL);
assert(r == 0);
r = pipe(fd);
assert(r == 0);
for (i = 0; i < 2; ++i) {
fcntl(fd[i], F_SETFD, fcntl(fd[i], F_GETFD) | FD_CLOEXEC);
fcntl(fd[i], F_SETFL, fcntl(fd[i], F_GETFL) | O_NONBLOCK);
}
ctx->control_fd_read = fd[0];
ctx->control_fd_write = fd[1];
/* Force an early rebuild when alsa_run is first called to ensure fds and
nfds have been initialized. */
ctx->rebuild = 1;
r = pthread_attr_init(&attr);
assert(r == 0);
r = pthread_attr_setstacksize(&attr, 256 * 1024);
assert(r == 0);
r = pthread_create(&ctx->thread, &attr, alsa_run_thread, ctx);
assert(r == 0);
r = pthread_attr_destroy(&attr);
assert(r == 0);
/* Open a dummy PCM to force the configuration space to be evaluated so that
init_local_config_with_workaround can find and modify the default node. */
r = alsa_locked_pcm_open(&dummy, SND_PCM_STREAM_PLAYBACK, NULL);
if (r >= 0) {
alsa_locked_pcm_close(dummy);
}
ctx->is_pa = 0;
pthread_mutex_lock(&cubeb_alsa_mutex);
ctx->local_config = init_local_config_with_workaround(CUBEB_ALSA_PCM_NAME);
pthread_mutex_unlock(&cubeb_alsa_mutex);
if (ctx->local_config) {
ctx->is_pa = 1;
r = alsa_locked_pcm_open(&dummy, SND_PCM_STREAM_PLAYBACK, ctx->local_config);
/* If we got a local_config, we found a PA PCM. If opening a PCM with that
config fails with EINVAL, the PA PCM is too old for this workaround. */
if (r == -EINVAL) {
pthread_mutex_lock(&cubeb_alsa_mutex);
snd_config_delete(ctx->local_config);
pthread_mutex_unlock(&cubeb_alsa_mutex);
ctx->local_config = NULL;
} else if (r >= 0) {
alsa_locked_pcm_close(dummy);
}
}
*context = ctx;
return CUBEB_OK;
}
/**
* Starts the thread. This method will signal to start the thread and
* return immediately. Note that the thread might not yet run when this
* method returns! The abstract method Main() is the entry point for the
* new thread. You have to implement the Main() method in your subclass.
*
* @see StartThread()
*/
int Thread::SignalStartThread() {
#if defined(WIN32)
LPVOID lpParameter;
hThread = CreateThread(
NULL, // no security attributes
MIN_STACK_SIZE,
__win32thread_launcher,
this,
0,
&lpThreadId);
if(hThread == NULL) {
std::cerr << "Thread creation failed: Error" << GetLastError() << std::endl << std::flush;
#if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
win32isRunning = false;
#else
RunningCondition.Set(false);
#endif
return -1;
}
return 0;
#else
// prepare the thread properties
int res = pthread_attr_setinheritsched(&__thread_attr, PTHREAD_EXPLICIT_SCHED);
if (res) {
std::cerr << "Thread creation failed: Could not inherit thread properties."
<< std::endl << std::flush;
RunningCondition.Set(false);
return res;
}
res = pthread_attr_setdetachstate(&__thread_attr, PTHREAD_CREATE_JOINABLE);
if (res) {
std::cerr << "Thread creation failed: Could not request a joinable thread."
<< std::endl << std::flush;
RunningCondition.Set(false);
return res;
}
res = pthread_attr_setscope(&__thread_attr, PTHREAD_SCOPE_SYSTEM);
if (res) {
std::cerr << "Thread creation failed: Could not request system scope for thread scheduling."
<< std::endl << std::flush;
RunningCondition.Set(false);
return res;
}
res = pthread_attr_setstacksize(&__thread_attr, MIN_STACK_SIZE);
if (res) {
std::cerr << "Thread creation failed: Could not set minimum stack size."
<< std::endl << std::flush;
RunningCondition.Set(false);
return res;
}
// Create and run the thread
res = pthread_create(&this->__thread_id, &__thread_attr, __pthread_launcher, this);
switch (res) {
case 0: // Success
break;
case EAGAIN:
std::cerr << "Thread creation failed: System doesn't allow to create another thread."
<< std::endl << std::flush;
RunningCondition.Set(false);
break;
case EPERM:
std::cerr << "Thread creation failed: You're lacking permisssions to set required scheduling policy and parameters."
<< std::endl << std::flush;
RunningCondition.Set(false);
break;
default:
std::cerr << "Thread creation failed: Unknown cause."
<< std::endl << std::flush;
RunningCondition.Set(false);
break;
}
return res;
#endif
}
//rtems_task Init(rtems_task_argument Argument)
void *POSIX_Init(void *argument)
{
pthread_attr_t threadAttr;
pthread_t theThread;
struct sched_param sched_param;
size_t stack_size;
int result;
char data[1000];
memset(data, 1, sizeof(data));
/* Set the TOD clock, so that gettimeofday() will work */
rtems_time_of_day fakeTime = { 2006, 3, 15, 17, 30, 0, 0 };
if (RTEMS_SUCCESSFUL != rtems_clock_set(&fakeTime))
{
assert(0);
}
/* Bring up the network stack so we can run the socket tests. */
initialize_network();
/* Start a POSIX thread for pjlib_test_main(), since that's what it
* thinks it is running in.
*/
/* Initialize attribute */
TEST( pthread_attr_init(&threadAttr) );
/* Looks like the rest of the attributes must be fully initialized too,
* or otherwise pthread_create will return EINVAL.
*/
/* Specify explicit scheduling request */
TEST( pthread_attr_setinheritsched(&threadAttr, PTHREAD_EXPLICIT_SCHED));
/* Timeslicing is needed by thread test, and this is accomplished by
* SCHED_RR.
*/
TEST( pthread_attr_setschedpolicy(&threadAttr, SCHED_RR));
/* Set priority */
TEST( pthread_attr_getschedparam(&threadAttr, &sched_param));
sched_param.sched_priority = NETWORK_STACK_PRIORITY - 10;
TEST( pthread_attr_setschedparam(&threadAttr, &sched_param));
/* Must have sufficient stack size (large size is needed by
* logger, because default settings for logger is to use message buffer
* from the stack).
*/
TEST( pthread_attr_getstacksize(&threadAttr, &stack_size));
if (stack_size < 8192)
TEST( pthread_attr_setstacksize(&threadAttr, 8192));
/* Create the thread for application */
result = pthread_create(&theThread, &threadAttr, &pjlib_test_main, NULL);
if (result != 0) {
my_perror(PJ_STATUS_FROM_OS(result),
"Error creating pjlib_test_main thread");
assert(!"Error creating main thread");
}
return NULL;
}
// create a new thread and attach to an activity
void SysThread::createThread()
{
pthread_attr_t newThreadAttr;
int schedpolicy, maxpri, minpri;
struct sched_param schedparam;
// Create an attr block for Thread.
pthread_attr_init(&newThreadAttr);
#if defined(LINUX) || defined(OPSYS_SUN) || defined(AIX)
/* scheduling on two threads controlled by the result method of the */
/* message object do not work properly without an enhanced priority */
pthread_getschedparam(pthread_self(), &schedpolicy, &schedparam);
#if defined(AIX)
// Starting with AIX 5.3 the priority for a thread created by
// a non root user can not be higher then 59. The priority
// of a user prog should not be higher then 59 (IBM AIX development).
schedparam.sched_priority = 59;
#else
# ifdef _POSIX_PRIORITY_SCHEDULING
maxpri = sched_get_priority_max(schedpolicy);
minpri = sched_get_priority_min(schedpolicy);
schedparam.sched_priority = (minpri + maxpri) / 2;
# endif
#endif
#if defined(OPSYS_SUN)
/* PTHREAD_EXPLICIT_SCHED ==> use scheduling attributes of the new object */
// pthread_attr_setinheritsched(&newThreadAttr, PTHREAD_EXPLICIT_SCHED);
/* Performance measurements show massive performance improvements > 50 % */
/* using Round Robin scheduling instead of FIFO scheduling */
pthread_attr_setschedpolicy(&newThreadAttr, SCHED_RR);
#endif
#if defined(AIX)
/* PTHREAD_EXPLICIT_SCHED ==> use scheduling attributes of the new object */
// pthread_attr_setinheritsched(&newThreadAttr, PTHREAD_EXPLICIT_SCHED);
/* Each thread has an initial priority that is dynamically modified by */
/* the scheduler, according to the thread's activity; thread execution */
/* is time-sliced. On other systems, this scheduling policy may be */
/* different. */
pthread_attr_setschedpolicy(&newThreadAttr, SCHED_OTHER);
#endif
pthread_attr_setschedparam(&newThreadAttr, &schedparam);
#endif
// Set the stack size.
pthread_attr_setstacksize(&newThreadAttr, THREAD_STACK_SIZE);
// Now create the thread
int rc = pthread_create(&_threadID, &newThreadAttr, call_thread_function, (void *)this);
if (rc != 0)
{
_threadID = 0;
fprintf(stderr," *** ERROR: At SysThread(), createThread - RC = %d !\n", rc);
}
pthread_attr_destroy(&newThreadAttr);
attached = false; // we own this thread
return;
}
/* Might be called back from NovaWin_StartExecService */
void StartServer(Policy *policy, GenericAgentConfig *config, ExecConfig *exec_config, const ReportContext *report_context)
{
#if !defined(__MINGW32__)
time_t now = time(NULL);
#endif
Promise *pp = NewPromise("exec_cfengine", "the executor agent");
Attributes dummyattr;
CfLock thislock;
pthread_attr_init(&threads_attrs);
pthread_attr_setdetachstate(&threads_attrs, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&threads_attrs, (size_t)2048*1024);
Banner("Starting executor");
memset(&dummyattr, 0, sizeof(dummyattr));
dummyattr.restart_class = "nonce";
dummyattr.transaction.ifelapsed = CF_EXEC_IFELAPSED;
dummyattr.transaction.expireafter = CF_EXEC_EXPIREAFTER;
if (!ONCE)
{
thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, dummyattr, pp, false);
if (thislock.lock == NULL)
{
DeletePromise(pp);
return;
}
/* Kill previous instances of cf-execd if those are still running */
Apoptosis();
/* FIXME: kludge. This code re-sets "last" lock to the one we have
acquired a few lines before. If the cf-execd is terminated, this lock
will be removed, and subsequent restart of cf-execd won't fail.
The culprit is Apoptosis(), which creates a promise and executes it,
taking locks during it, so CFLOCK/CFLAST/CFLOG get reset.
Proper fix is to keep all the taken locks in the memory, and release
all of them during process termination.
*/
strcpy(CFLOCK, thislock.lock);
strcpy(CFLAST, thislock.last ? thislock.last : "");
strcpy(CFLOG, thislock.log ? thislock.log : "");
}
#ifdef __MINGW32__
if (!NO_FORK)
{
CfOut(cf_verbose, "", "Windows does not support starting processes in the background - starting in foreground");
}
#else /* !__MINGW32__ */
if ((!NO_FORK) && (fork() != 0))
{
CfOut(cf_inform, "", "cf-execd starting %.24s\n", cf_ctime(&now));
_exit(0);
}
if (!NO_FORK)
{
ActAsDaemon(0);
}
#endif /* !__MINGW32__ */
WritePID("cf-execd.pid");
signal(SIGINT, HandleSignalsForDaemon);
signal(SIGTERM, HandleSignalsForDaemon);
signal(SIGHUP, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGUSR1, HandleSignalsForDaemon);
signal(SIGUSR2, HandleSignalsForDaemon);
umask(077);
if (ONCE)
{
CfOut(cf_verbose, "", "Sleeping for splaytime %d seconds\n\n", SPLAYTIME);
sleep(SPLAYTIME);
LocalExec(exec_config);
CloseLog();
}
else
{
while (!IsPendingTermination())
{
if (ScheduleRun(&policy, config, exec_config, report_context))
{
CfOut(cf_verbose, "", "Sleeping for splaytime %d seconds\n\n", SPLAYTIME);
sleep(SPLAYTIME);
if (!LocalExecInThread(exec_config))
{
CfOut(cf_inform, "", "Unable to run agent in thread, falling back to blocking execution");
//.........这里部分代码省略.........
sc_cor*
sc_cor_pkg_pthread::create( std::size_t stack_size, sc_cor_fn* fn, void* arg )
{
sc_cor_pthread* cor_p = new sc_cor_pthread;
DEBUGF << &main_cor << ": sc_cor_pkg_pthread::create("
<< cor_p << ")" << std::endl;
// INITIALIZE OBJECT'S FIELDS FROM ARGUMENT LIST:
cor_p->m_pkg_p = this;
cor_p->m_cor_fn = fn;
cor_p->m_cor_fn_arg = arg;
// SET UP THREAD CREATION ATTRIBUTES:
//
// Use default values except for stack size. If stack size is non-zero
// set it.
pthread_attr_t attr;
pthread_attr_init( &attr );
if ( stack_size != 0 )
{
pthread_attr_setstacksize( &attr, stack_size );
}
// ALLOCATE THE POSIX THREAD TO USE AND FORCE SEQUENTIAL EXECUTION:
//
// Because pthread_create causes the created thread to be executed,
// we need to let it run until we can block in the invoke_module_method.
// So we:
// (1) Lock the creation mutex before creating the new thread.
// (2) Sleep on the creation condition, which will be signalled by
// the newly created thread just before it goes to sleep in
// invoke_module_method.
// This scheme results in the newly created thread being dormant before
// the main thread continues execution.
pthread_mutex_lock( &create_mutex );
DEBUGF << &main_cor << ": about to create actual thread "
<< cor_p << std::endl;
if ( pthread_create( &cor_p->m_thread, &attr,
&sc_cor_pthread::invoke_module_method, (void*)cor_p ) )
{
std::fprintf(stderr, "ERROR - could not create thread\n");
}
DEBUGF << &main_cor << ": main thread waiting for signal from "
<< cor_p << std::endl;
pthread_cond_wait( &create_condition, &create_mutex );
DEBUGF << &main_cor << ": main thread signaled by "
<< cor_p << endl;
pthread_attr_destroy( &attr );
pthread_mutex_unlock( &create_mutex );
DEBUGF << &main_cor << ": exiting sc_cor_pkg_pthread::create("
<< cor_p << ")" << std::endl;
return cor_p;
}
请发表评论