diff options
| -rw-r--r-- | src/gos/gfx_linux.c | 171 | ||||
| -rw-r--r-- | src/gos/gfx_linux.h | 31 | ||||
| -rw-r--r-- | src/gos/gfx_osx.c | 42 | ||||
| -rw-r--r-- | src/gwin/gwin_progressbar.c | 41 | ||||
| -rw-r--r-- | src/gwin/gwin_progressbar.h | 7 | 
5 files changed, 166 insertions, 126 deletions
diff --git a/src/gos/gfx_linux.c b/src/gos/gfx_linux.c index fc716ec9..e6fbe26c 100644 --- a/src/gos/gfx_linux.c +++ b/src/gos/gfx_linux.c @@ -14,8 +14,6 @@  #include <stdio.h>  #include <unistd.h> -#include <errno.h> -#include <sys/time.h>  #include <time.h>  #if USE_SCHED_NOT_PTHREAD_YIELD  	#include <sched.h> @@ -70,16 +68,16 @@ void gfxSleepMilliseconds(delaytime_t ms) {  		default:  			ts.tv_sec = ms / 1000; -			ts.tv_nsec = (ms % 1000) * 1000; +			ts.tv_nsec = (ms % 1000) * 1000000;  			nanosleep(&ts, 0);  			return;  	}  } -void gfxSleepMicroseconds(delaytime_t ms) { +void gfxSleepMicroseconds(delaytime_t us) {  	struct timespec	ts; -	switch(ms) { +	switch(us) {  		case TIME_IMMEDIATE:  			linuxyield();  			return; @@ -90,8 +88,8 @@ void gfxSleepMicroseconds(delaytime_t ms) {  			return;  		default: -			ts.tv_sec = ms / 1000000; -			ts.tv_nsec = ms % 1000000; +			ts.tv_sec = us / 1000000; +			ts.tv_nsec = (us % 1000000) * 1000;  			nanosleep(&ts, 0);  			return;  	} @@ -101,8 +99,7 @@ systemticks_t gfxSystemTicks(void) {  	struct timespec	ts;  	clock_gettime(CLOCK_MONOTONIC, &ts); - -	return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; +	return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;  }  gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { @@ -133,81 +130,119 @@ threadreturn_t gfxThreadWait(gfxThreadHandle thread) {  	return retval;  } -void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { -	pthread_mutex_init(&pSem->mtx, 0); -	pthread_cond_init(&pSem->cond, 0); -	pthread_mutex_lock(&pSem->mtx); -	pSem->cnt = val; -	pSem->max = limit; -	pthread_mutex_unlock(&pSem->mtx); -} - -void gfxSemDestroy(gfxSem *pSem) { -	pthread_mutex_destroy(&pSem->mtx); -	pthread_cond_destroy(&pSem->cond); -} - -bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { -	pthread_mutex_lock(&pSem->mtx); - -	switch (ms) { +#if GFX_USE_POSIX_SEMAPHORES +	void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { +		pSem->max = limit; +		sem_init(&pSem->sem, 0, val); +	} +	void gfxSemDestroy(gfxSem *pSem) { +		sem_destroy(&pSem->sem); +	} +	bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { +		switch (ms) {  		case TIME_INFINITE: -			while (!pSem->cnt) -				pthread_cond_wait(&pSem->cond, &pSem->mtx); -			break; +			return sem_wait(&pSem->sem) ? FALSE : TRUE;  		case TIME_IMMEDIATE: -			if (!pSem->cnt) { -				pthread_mutex_unlock(&pSem->mtx); -				return FALSE; -			} -			break; +			return sem_trywait(&pSem->sem) ? FALSE : TRUE;  		default:  			{ -				struct timeval now;  				struct timespec	tm; -				gettimeofday(&now, 0); -				tm.tv_sec = now.tv_sec + ms / 1000; -				tm.tv_nsec = (now.tv_usec + ms % 1000) * 1000; -				while (!pSem->cnt) { -					if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm) == ETIMEDOUT) { -						pthread_mutex_unlock(&pSem->mtx); -						return FALSE; -					} -				} +				clock_gettime(CLOCK_REALTIME, &tm); +				tm.tv_sec += ms / 1000; +				tm.tv_nsec += (ms % 1000) * 1000000; +				return sem_timedwait(&pSem->sem, &tm) ? FALSE : TRUE;  			} -			break; +		}  	} +	void gfxSemSignal(gfxSem *pSem) { +		if (gfxSemCounter(pSem) < pSem->max) +			sem_post(&pSem->sem); +	} +	semcount_t gfxSemCounter(gfxSem *pSem) { +		int	res; -	pSem->cnt--; -	pthread_mutex_unlock(&pSem->mtx); - -	return TRUE; -} - -void gfxSemSignal(gfxSem *pSem) { -	pthread_mutex_lock(&pSem->mtx); +		res = 0; +		sem_getvalue(&pSem->sem, &res); +		return res; +	} +#else +	void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { +		pthread_mutex_init(&pSem->mtx, 0); +		pthread_cond_init(&pSem->cond, 0); +		pthread_mutex_lock(&pSem->mtx); +		pSem->cnt = val; +		pSem->max = limit; +		pthread_mutex_unlock(&pSem->mtx); +	} +	void gfxSemDestroy(gfxSem *pSem) { +		pthread_mutex_destroy(&pSem->mtx); +		pthread_cond_destroy(&pSem->cond); +	} +	bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { +		pthread_mutex_lock(&pSem->mtx); + +		switch (ms) { +			case TIME_INFINITE: +				while (!pSem->cnt) +					pthread_cond_wait(&pSem->cond, &pSem->mtx); +				break; + +			case TIME_IMMEDIATE: +				if (!pSem->cnt) { +					pthread_mutex_unlock(&pSem->mtx); +					return FALSE; +				} +				break; + +			default: +				{ +					struct timespec	tm; + +					clock_gettime(CLOCK_REALTIME, &tm); +					tm.tv_sec += ms / 1000; +					tm.tv_nsec += (ms % 1000) * 1000000; +					while (!pSem->cnt) { +						// We used to test the return value for ETIMEDOUT. This doesn't +						//	work in some current pthread libraries which return -1 instead +						//	and set errno to ETIMEDOUT. So, we will return FALSE on any error +						//	including a ETIMEDOUT. +						if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { +							pthread_mutex_unlock(&pSem->mtx); +							return FALSE; +						} +					} +				} +				break; +		} -	if (pSem->cnt < pSem->max) { -		pSem->cnt++; -		pthread_cond_signal(&pSem->cond); +		pSem->cnt--; +		pthread_mutex_unlock(&pSem->mtx); +		return TRUE;  	} +	void gfxSemSignal(gfxSem *pSem) { +		pthread_mutex_lock(&pSem->mtx); -	pthread_mutex_unlock(&pSem->mtx); -} +		if (pSem->cnt < pSem->max) { +			pSem->cnt++; +			pthread_cond_signal(&pSem->cond); +		} -semcount_t gfxSemCounter(gfxSem *pSem) { -	semcount_t	res; +		pthread_mutex_unlock(&pSem->mtx); +	} +	semcount_t gfxSemCounter(gfxSem *pSem) { +		semcount_t	res; -	// The locking is really only required if obtaining the count is a divisible operation -	//	which it might be on a 8/16 bit processor with a 32 bit semaphore count. -	pthread_mutex_lock(&pSem->mtx); -	res = pSem->cnt; -	pthread_mutex_unlock(&pSem->mtx); +		// The locking is really only required if obtaining the count is a divisible operation +		//	which it might be on a 8/16 bit processor with a 32 bit semaphore count. +		pthread_mutex_lock(&pSem->mtx); +		res = pSem->cnt; +		pthread_mutex_unlock(&pSem->mtx); -	return res; -} +		return res; +	} +#endif // GFX_USE_POSIX_SEMAPHORES  #endif /* GFX_USE_OS_LINUX */ diff --git a/src/gos/gfx_linux.h b/src/gos/gfx_linux.h index bd31184e..39cfbc85 100644 --- a/src/gos/gfx_linux.h +++ b/src/gos/gfx_linux.h @@ -10,11 +10,20 @@  #if GFX_USE_OS_LINUX +// We don't put this in the general sys_options.h as it is Linux specific. +#ifndef GFX_USE_POSIX_SEMAPHORES +	#define GFX_USE_POSIX_SEMAPHORES	TRUE +#endif +  #include <sys/types.h>  #include <stdlib.h>  #include <stdint.h>  #include <pthread.h> +#if GFX_USE_POSIX_SEMAPHORES +	#include <semaphore.h> +#endif +  /* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */  typedef int8_t				bool_t; @@ -42,7 +51,6 @@ typedef pthread_mutex_t		gfxMutex;  #define gfxMutexExit(pmtx)				pthread_mutex_unlock(pmtx)  #define gfxSemWaitI(psem)				gfxSemWait(psem, TIME_IMMEDIATE)  #define gfxSemSignalI(psem)				gfxSemSignal(psem) -#define gfxSemCounterI(pSem)			((pSem)->cnt)  #define TIME_IMMEDIATE				0  #define TIME_INFINITE				((delaytime_t)-1) @@ -51,12 +59,21 @@ typedef pthread_mutex_t		gfxMutex;  #define NORMAL_PRIORITY				0  #define HIGH_PRIORITY				-10 -typedef struct gfxSem { -	pthread_mutex_t	mtx; -	pthread_cond_t	cond; -	semcount_t		cnt; -	semcount_t		max; -} gfxSem; +#if GFX_USE_POSIX_SEMAPHORES +	typedef struct gfxSem { +		sem_t			sem; +		semcount_t		max; +	} gfxSem; +	#define gfxSemCounterI(psem)	gfxSemCounter(psem) +#else +	typedef struct gfxSem { +		pthread_mutex_t	mtx; +		pthread_cond_t	cond; +		semcount_t		cnt; +		semcount_t		max; +	} gfxSem; +	#define gfxSemCounterI(psem)	((psem)->cnt) +#endif  /*===========================================================================*/  /* Function declarations.                                                    */ diff --git a/src/gos/gfx_osx.c b/src/gos/gfx_osx.c index f2e58f77..f21b8a75 100644 --- a/src/gos/gfx_osx.c +++ b/src/gos/gfx_osx.c @@ -21,18 +21,6 @@  static gfxMutex		SystemMutex; - -void get_ticks(mach_timespec_t *mts){ -	clock_serv_t cclock; -	//mach_timespec_t mts; - -	host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); -	clock_get_time(cclock, mts); -	mach_port_deallocate(mach_task_self(), cclock); - - -} -  void _gosInit(void)  {  	/* No initialization of the operating system itself is needed */ @@ -66,35 +54,35 @@ void gfxSleepMilliseconds(delaytime_t ms) {  	case TIME_INFINITE:		while(1) sleep(60);			return;  	default:  		ts.tv_sec = ms / 1000; -		ts.tv_nsec = (ms % 1000) * 1000; +		ts.tv_nsec = (ms % 1000) * 1000000;  		nanosleep(&ts, 0);  		return;  	}  } -void gfxSleepMicroseconds(delaytime_t ms) { +void gfxSleepMicroseconds(delaytime_t us) {  	struct timespec	ts; -	switch(ms) { +	switch(us) {  	case TIME_IMMEDIATE:	gfxYield();			return;  	case TIME_INFINITE:		while(1) sleep(60);			return;  	default: -		ts.tv_sec = ms / 1000000; -		ts.tv_nsec = ms % 1000000; +		ts.tv_sec = us / 1000000; +		ts.tv_nsec = (us % 1000000) * 1000;  		nanosleep(&ts, 0);  		return;  	}  }  systemticks_t gfxSystemTicks(void) { -	//struct timespec	ts; -	//clock_gettime(CLOCK_MONOTONIC, &ts); - -	mach_timespec_t ts; -	get_ticks(&ts); +	mach_timespec_t	ts; +	clock_serv_t	cclock; +	host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); +	clock_get_time(cclock, &ts); +	mach_port_deallocate(mach_task_self(), cclock); -	return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; +	return ts.tv_sec * 1000UL + ts.tv_nsec / 1000000;  }  gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { @@ -157,9 +145,13 @@ bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) {  			gettimeofday(&now, 0);  			tm.tv_sec = now.tv_sec + ms / 1000; -			tm.tv_nsec = (now.tv_usec + ms % 1000) * 1000; +			tm.tv_nsec = now.tv_usec * 1000 + (ms % 1000) * 1000000;  			while (!pSem->cnt) { -				if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm) == ETIMEDOUT) { +				// We used to test the return value for ETIMEDOUT. This doesn't +				//	work in some current pthread libraries which return -1 instead +				//	and set errno to ETIMEDOUT. So, we will return FALSE on any error +				//	including a ETIMEDOUT. +				if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) {  					pthread_mutex_unlock(&pSem->mtx);  					return FALSE;  				} diff --git a/src/gwin/gwin_progressbar.c b/src/gwin/gwin_progressbar.c index ef28e8dc..d5b8721a 100644 --- a/src/gwin/gwin_progressbar.c +++ b/src/gwin/gwin_progressbar.c @@ -79,13 +79,12 @@ GHandle gwinGProgressbarCreate(GDisplay *g, GProgressbarObject *gs, const GWidge  	gs->pos = 0;  	#if GWIN_PROGRESSBAR_AUTO -		gs->delay = 0;  		gtimerInit(&gs->gt);  	#endif  	ResetDisplayPos(gs);  	gwinSetVisible((GHandle)gs, pInit->g.show); -	 +  	return (GHandle)gs;  } @@ -183,39 +182,37 @@ void gwinProgressbarDecrement(GHandle gh) {  	static void _progressbarCallback(void *param) {  		#define gsw		((GProgressbarObject *)gh)  		GHandle gh = (GHandle)param; -	 +  		if (gh->vmt != (gwinVMT *)&progressbarVMT)  			return; -	 +  		gwinProgressbarIncrement(gh); -	 -		if (gsw->pos < gsw->max) -			gtimerStart(&(gsw->gt), _progressbarCallback, gh, FALSE, gsw->delay); -	 -		#undef gsw	 + +		if (gsw->pos >= gsw->max) +			gtimerStop(&gsw->gt); + +		#undef gsw  	} -	 +  	void gwinProgressbarStart(GHandle gh, delaytime_t delay) {  		#define gsw		((GProgressbarObject *)gh) -	 +  		if (gh->vmt != (gwinVMT *)&progressbarVMT)  			return; -	 -		gsw->delay = delay; -	 -		gtimerStart(&(gsw->gt), _progressbarCallback, gh, FALSE, gsw->delay); -	 + +		gtimerStart(&gsw->gt, _progressbarCallback, gh, TRUE, delay); +  		#undef gsw  	} -	 +  	void gwinProgressbarStop(GHandle gh) {  		#define gsw		((GProgressbarObject *)gh) -	 +  		if (gh->vmt != (gwinVMT *)&progressbarVMT)  			return; -	 -		gtimerStop(&(gsw->gt)); -	 + +		gtimerStop(&gsw->gt); +  		#undef gsw  	}  #endif /* GWIN_PROGRESSBAR_AUTO */ @@ -226,7 +223,7 @@ void gwinProgressbarDecrement(GHandle gh) {  void gwinProgressbarDraw_Std(GWidgetObject *gw, void *param) {  	#define gsw			((GProgressbarObject *)gw) -	 +  	const GColorSet *	pcol;  	(void)				param; diff --git a/src/gwin/gwin_progressbar.h b/src/gwin/gwin_progressbar.h index 49c11a98..dae9d40a 100644 --- a/src/gwin/gwin_progressbar.h +++ b/src/gwin/gwin_progressbar.h @@ -33,7 +33,6 @@ typedef struct GProgressbarObject {  	int					pos;  	#if GWIN_PROGRESSBAR_AUTO  		GTimer			gt; -		delaytime_t		delay;  	#endif  } GProgressbarObject; @@ -59,7 +58,7 @@ extern "C" {   * @note				A progressbar does not take any GINPUT inputs.   *   * @api - */	 + */  GHandle gwinGProgressbarCreate(GDisplay *g, GProgressbarObject *gb, const GWidgetInit *pInit);  #define gwinProgressbarCreate(w, pInit)			gwinGProgressbarCreate(GDISP, w, pInit) @@ -165,14 +164,14 @@ void gwinProgressbarDecrement(GHandle gh);  	 * @api  	 */  	void gwinProgressbarStart(GHandle gh, delaytime_t delay); -	 +  	/**  	 * @brief	Stop the timer which is started by @p gwinProgressbarStart()  	 *  	 * @param[in] gh		The window handle (must be a progressbar window)  	 *  	 * @api -	 */		 +	 */  	void gwinProgressbarStop(GHandle gh);  #endif /* GWIN_PROGRESSBAR_AUTO */  | 
