XQuartz: Cleaned up startup and thread creation a tad.

(cherry picked from commit c861fe00e112b21ee0156d09a6cd5281642a1dcc)
This commit is contained in:
Jeremy Huddleston 2008-04-26 19:21:05 -07:00
parent b114d4e861
commit ef1c520537
10 changed files with 95 additions and 98 deletions

View File

@ -237,12 +237,11 @@ static int indexForScanlinePad[ 65 ] = {
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif #endif
#ifdef __APPLE__ #ifdef XQUARTZ
void DarwinHandleGUI(int argc, char **argv, char **envp); int dix_main(int argc, char *argv[], char *envp[])
#else
int main(int argc, char *argv[], char *envp[])
#endif #endif
int
main(int argc, char *argv[], char *envp[])
{ {
int i, j, k, error; int i, j, k, error;
char *xauthfile; char *xauthfile;
@ -256,13 +255,6 @@ main(int argc, char *argv[], char *envp[])
PrinterInitGlobals(); PrinterInitGlobals();
#endif #endif
#ifdef XQUARTZ
/* Quartz support on Mac OS X requires that the Cocoa event loop be in
* the main thread. This allows the X server main to be called again
* from another thread. */
DarwinHandleGUI(argc, argv, envp);
#endif
CheckUserParameters(argc, argv, envp); CheckUserParameters(argc, argv, envp);
CheckUserAuthorization(); CheckUserAuthorization();

View File

@ -71,7 +71,7 @@ void X11ApplicationSetCanQuit (int state);
void X11ApplicationServerReady (void); void X11ApplicationServerReady (void);
void X11ApplicationShowHideMenubar (int state); void X11ApplicationShowHideMenubar (int state);
void X11ApplicationMain(int argc, const char **argv, void (*server_thread) (void *), void *server_arg); void X11ApplicationMain(int argc, const char **argv);
extern int X11EnableKeyEquivalents; extern int X11EnableKeyEquivalents;
extern int quartzHasRoot, quartzEnableRootless; extern int quartzHasRoot, quartzEnableRootless;

View File

@ -35,6 +35,7 @@
#include "quartzForeground.h" #include "quartzForeground.h"
#include "quartzCommon.h" #include "quartzCommon.h"
#import "X11Application.h" #import "X11Application.h"
# include "darwin.h" # include "darwin.h"
@ -45,7 +46,9 @@
# include "micmap.h" # include "micmap.h"
#include <mach/mach.h> #include <mach/mach.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h> #include <pthread.h>
extern pthread_cond_t server_can_start_cond;
#define DEFAULTS_FILE "/usr/X11/lib/X11/xserver/Xquartz.plist" #define DEFAULTS_FILE "/usr/X11/lib/X11/xserver/Xquartz.plist"
@ -732,19 +735,6 @@ void X11ApplicationShowHideMenubar (int state) {
[n release]; [n release];
} }
static pthread_t create_thread (void *func, void *arg) {
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init (&attr);
pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&tid, &attr, func, arg);
pthread_attr_destroy (&attr);
return tid;
}
static void check_xinitrc (void) { static void check_xinitrc (void) {
char *tem, buf[1024]; char *tem, buf[1024];
NSString *msg; NSString *msg;
@ -786,7 +776,7 @@ environment?", @"Startup xinitrc dialog");
[X11App prefs_synchronize]; [X11App prefs_synchronize];
} }
void X11ApplicationMain (int argc, const char **argv, void (*server_thread) (void *), void *server_arg) { void X11ApplicationMain (int argc, const char **argv) {
NSAutoreleasePool *pool; NSAutoreleasePool *pool;
#ifdef DEBUG #ifdef DEBUG
@ -813,15 +803,8 @@ void X11ApplicationMain (int argc, const char **argv, void (*server_thread) (voi
aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
NSMaxY([[NSScreen mainScreen] visibleFrame]); NSMaxY([[NSScreen mainScreen] visibleFrame]);
APPKIT_THREAD = pthread_self(); /* Tell the server thread that it can proceed */
SERVER_THREAD = create_thread (server_thread, server_arg); pthread_cond_broadcast(&server_can_start_cond);
if (!SERVER_THREAD) {
ErrorF("can't create secondary thread\n");
exit (1);
}
QuartzMoveToForeground();
[NSApp run]; [NSApp run];
/* not reached */ /* not reached */

View File

@ -100,6 +100,6 @@
#endif /* __OBJC__ */ #endif /* __OBJC__ */
void X11ControllerMain(int argc, const char **argv, void (*server_thread) (void *), void *server_arg); void X11ControllerMain(int argc, const char **argv);
#endif /* X11CONTROLLER_H */ #endif /* X11CONTROLLER_H */

View File

@ -756,6 +756,6 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
@end @end
void X11ControllerMain(int argc, const char **argv, void (*server_thread) (void *), void *server_arg) { void X11ControllerMain(int argc, const char **argv) {
X11ApplicationMain (argc, argv, server_thread, server_arg); X11ApplicationMain (argc, argv);
} }

View File

@ -78,7 +78,8 @@ static int old_flags = 0; // last known modifier state
xEvent *darwinEvents = NULL; xEvent *darwinEvents = NULL;
pthread_mutex_t mieqEnqueue_mutex; pthread_mutex_t mieqEnqueue_mutex = PTHREAD_MUTEX_INITIALIZER;
static inline void mieqEnqueue_lock(void) { static inline void mieqEnqueue_lock(void) {
int err; int err;
if((err = pthread_mutex_lock(&mieqEnqueue_mutex))) { if((err = pthread_mutex_lock(&mieqEnqueue_mutex))) {
@ -303,17 +304,11 @@ static void DarwinEventHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, in
} }
Bool DarwinEQInit(DevicePtr pKbd, DevicePtr pPtr) { Bool DarwinEQInit(DevicePtr pKbd, DevicePtr pPtr) {
int err;
if (!darwinEvents) if (!darwinEvents)
darwinEvents = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum()); darwinEvents = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
if (!darwinEvents) if (!darwinEvents)
FatalError("Couldn't allocate event buffer\n"); FatalError("Couldn't allocate event buffer\n");
if((err = pthread_mutex_init(&mieqEnqueue_mutex, NULL))) {
FatalError("Couldn't allocate mieqEnqueue mutex: %d.\n", err);
}
mieqInit(); mieqInit();
mieqSetHandler(kXquartzReloadKeymap, DarwinKeyboardReloadHandler); mieqSetHandler(kXquartzReloadKeymap, DarwinKeyboardReloadHandler);
mieqSetHandler(kXquartzActivate, DarwinEventHandler); mieqSetHandler(kXquartzActivate, DarwinEventHandler);

View File

@ -39,7 +39,6 @@
#include "quartz.h" #include "quartz.h"
#include "darwin.h" #include "darwin.h"
#include "darwinEvents.h" #include "darwinEvents.h"
#include "quartzAudio.h"
#include "pseudoramiX.h" #include "pseudoramiX.h"
#define _APPLEWM_SERVER_ #define _APPLEWM_SERVER_
#include "applewmExt.h" #include "applewmExt.h"
@ -156,10 +155,6 @@ void QuartzInitOutput(
int argc, int argc,
char **argv ) char **argv )
{ {
if (serverGeneration == 1) {
QuartzAudioInit();
}
if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler,
QuartzWakeupHandler, QuartzWakeupHandler,
NULL)) NULL))

View File

@ -37,42 +37,64 @@
#include <unistd.h> #include <unistd.h>
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include "quartzCommon.h" #include "quartzCommon.h"
#include "quartzForeground.h"
#include "X11Controller.h" #include "X11Controller.h"
#include "darwin.h" #include "darwin.h"
#include "darwinEvents.h"
#include "quartzAudio.h"
#include "quartz.h" #include "quartz.h"
#include "opaque.h" #include "opaque.h"
#include "micmap.h" #include "micmap.h"
#include <assert.h> #include <assert.h>
char **envpGlobal; // argcGlobal and argvGlobal #include <pthread.h>
// are from dix/globals.c
int main(int argc, char **argv, char **envp); int dix_main(int argc, char **argv, char **envp);
void _InitHLTB(void);
void DarwinHandleGUI(int argc, char **argv, char **envp); struct arg {
int argc;
char **argv;
char **envp;
};
pthread_cond_t server_can_start_cond = PTHREAD_COND_INITIALIZER;
static void server_thread (void *arg) { static void server_thread (void *arg) {
exit (main (argcGlobal, argvGlobal, envpGlobal)); struct arg *args = (struct arg *)arg;
/* Wait to be told we can continue */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
pthread_cond_wait(&server_can_start_cond, &mutex);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
exit (dix_main(args->argc, args->argv, args->envp));
} }
/* static pthread_t create_thread (void *func, void *arg) {
* DarwinHandleGUI pthread_attr_t attr;
* This function is called first from main(). The first time pthread_t tid;
* it is called we start the Mac OS X front end. The front end
* will call main() again from another thread to run the X pthread_attr_init (&attr);
* server. On the second call this function loads the user pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
* preferences set by the Mac OS X front end. pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
*/ pthread_create (&tid, &attr, func, arg);
void DarwinHandleGUI(int argc, char **argv, char **envp) { pthread_attr_destroy (&attr);
static Bool been_here = FALSE;
return tid;
}
int main(int argc, char **argv, char **envp) {
int i; int i;
int fd[2]; int fd[2];
if (been_here) { /* Store the args to pass to dix_main() */
return; struct arg args;
} args.argc = argc;
been_here = TRUE; args.argv = argv;
args.envp = envp;
// Make a pipe to pass events // Make a pipe to pass events
assert( pipe(fd) == 0 ); assert( pipe(fd) == 0 );
@ -80,11 +102,6 @@ void DarwinHandleGUI(int argc, char **argv, char **envp) {
darwinEventWriteFD = fd[1]; darwinEventWriteFD = fd[1];
fcntl(darwinEventReadFD, F_SETFL, O_NONBLOCK); fcntl(darwinEventReadFD, F_SETFL, O_NONBLOCK);
// Store command line arguments to pass back to main()
argcGlobal = argc;
argvGlobal = argv;
envpGlobal = envp;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
// Display version info without starting Mac OS X UI if requested // Display version info without starting Mac OS X UI if requested
if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) { if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) {
@ -93,16 +110,20 @@ void DarwinHandleGUI(int argc, char **argv, char **envp) {
} }
} }
/* Initially I ran the X server on the main thread, and received /* Create the audio mutex */
events on the second thread. But now we may be using Carbon, QuartzAudioInit();
that needs to run on the main thread. (Otherwise, when it's
prebound, it will initialize itself on the wrong thread)
grr.. but doing that means that if the X thread gets scheduled pthread_cond_init(&server_can_start_cond, NULL);
before the main thread when we're _not_ prebound, things fail,
so initialize by hand. */
_InitHLTB(); APPKIT_THREAD_ID = pthread_self();
X11ControllerMain(argc, (const char **)argv, server_thread, NULL); SERVER_THREAD_ID = create_thread(server_thread, &args);
if (!SERVER_THREAD_ID) {
ErrorF("can't create secondary thread\n");
exit (1);
}
QuartzMoveToForeground();
X11ControllerMain(argc, (const char **)argv);
exit(0); exit(0);
} }

View File

@ -33,8 +33,8 @@
#include <execinfo.h> #include <execinfo.h>
pthread_t SERVER_THREAD; pthread_t APPKIT_THREAD_ID;
pthread_t APPKIT_THREAD; pthread_t SERVER_THREAD_ID;
void spewCallStack(void) { void spewCallStack(void) {
void* callstack[128]; void* callstack[128];
@ -48,7 +48,7 @@ void spewCallStack(void) {
free(strs); free(strs);
} }
void _threadAssert(pthread_t tid, const char *file, const char *fun, int line) { void _threadSafetyAssert(pthread_t tid, const char *file, const char *fun, int line) {
if(pthread_equal(pthread_self(), tid)) if(pthread_equal(pthread_self(), tid))
return; return;
@ -58,3 +58,13 @@ void _threadAssert(pthread_t tid, const char *file, const char *fun, int line) {
file, fun, line); file, fun, line);
spewCallStack(); spewCallStack();
} }
const char *threadSafetyID(pthread_t tid) {
if(pthread_equal(tid, APPKIT_THREAD_ID)) {
return "Appkit Thread";
} else if(pthread_equal(tid, SERVER_THREAD_ID)) {
return "Xserver Thread";
} else {
return "Unknown Thread";
}
}

View File

@ -31,22 +31,23 @@
#include <pthread.h> #include <pthread.h>
extern pthread_t SERVER_THREAD; extern pthread_t APPKIT_THREAD_ID;
extern pthread_t APPKIT_THREAD; extern pthread_t SERVER_THREAD_ID;
#define threadSafetyID(tid) (pthread_equal((tid), SERVER_THREAD) ? "X Server Thread" : "Appkit Thread")
/* Dump the call stack */ /* Dump the call stack */
void spewCallStack(void); void spewCallStack(void);
/* Print message to ErrorF if we're in the wrong thread */ /* Print message to ErrorF if we're in the wrong thread */
void _threadAssert(pthread_t tid, const char *file, const char *fun, int line); void _threadSafetyAssert(pthread_t tid, const char *file, const char *fun, int line);
#define threadAssert(tid) _threadAssert(tid, __FILE__, __FUNCTION__, __LINE__) /* Get a string that identifies our thread nicely */
const char *threadSafetyID(pthread_t tid);
#define threadSafetyAssert(tid) _threadSafetyAssert(tid, __FILE__, __FUNCTION__, __LINE__)
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
#define TA_SERVER() threadAssert(SERVER_THREAD) #define TA_APPKIT() threadSafetyAssert(APPKIT_THREAD_ID)
#define TA_APPKIT() threadAssert(APPKIT_THREAD) #define TA_SERVER() threadSafetyAssert(SERVER_THREAD_ID)
#else #else
#define TA_SERVER() #define TA_SERVER()
#define TA_APPKIT() #define TA_APPKIT()