1 //////////////////////////////////////////////////////////////////////
2 //
3 // Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 // File : os.cpp
27 // Classes : -
28 // Description : OS dependent functions
29 //
30 ////////////////////////////////////////////////////////////////////////
31
32 // Needs to be first, or clashes with other definitions
33 #if defined(__APPLE__) || defined(__APPLE_CC__) // guard against __APPLE__ being undef from ftlk
34 #include <CoreServices/CoreServices.h> // For FSRef, FSRefMakePath, FSFindFolder
35 #endif
36
37 #include "os.h"
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <time.h>
42 #include <string.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45
46 // Needed for OSX 10.2.x fix
47 #if defined(__APPLE__) || defined(__APPLE_CC__) // guard against __APPLE__ being undef from ftlk
48 #include <stdio.h>
49 #endif
50
51 // Environment seperators
52 #ifdef _WINDOWS
53 // >> Windoze
54 #include <io.h>
55 #include <direct.h>
56 #include <errno.h>
57
58
59 // << Windows
60 #else
61 // >> Unix
62 #include <sys/param.h>
63 #include <sys/sysctl.h>
64 #include <dlfcn.h>
65 #include <glob.h>
66
67 // << Unix
68 #endif
69
70 #ifdef HAVE_SYS_TIME_H
71 #ifdef TIME_WITH_SYS_TIME
72 #include <sys/time.h>
73 #endif
74 #endif
75
76 #ifndef HAVE_GETTIMEOFDAY
77 #include <sys/timeb.h>
78
gettimeofday(struct timeval * tv,void * time_zone)79 static void gettimeofday(struct timeval *tv,void* time_zone) {
80 timeb cur;
81
82 ftime(&cur);
83
84 tv->tv_sec = (long) cur.time;
85 tv->tv_usec = cur.millitm * 1000;
86 }
87 #endif
88
89
90 ///////////////////////////////////////////////////////////////////////
91 // These two hold the operating start time
92 static time_t osStartTimeSec;
93 static time_t osStartTimeMsec;
94
95
96
97
98
99
100
101
102 ///////////////////////////////////////////////////////////////////////
103 // Funvtion : osInit
104 // Description : Initialize the operating system
105 // Return Value : -
106 // Comments :
osInit()107 void osInit() {
108 struct timeval ti;
109
110 gettimeofday(&ti, NULL);
111
112 osStartTimeSec = ti.tv_sec;
113 osStartTimeMsec = ti.tv_usec;
114 }
115
116 ///////////////////////////////////////////////////////////////////////
117 // Funvtion : osShutdown
118 // Description : Shutdown the operating system
119 // Return Value : -
120 // Comments :
osShutdown()121 void osShutdown() {
122 }
123
124
125 ///////////////////////////////////////////////////////////////////////
126 // Funvtion : osLoadModule
127 // Description : Load / attach a dll/so file
128 // Return Value : The module handle
129 // Comments :
osLoadModule(const char * name)130 void *osLoadModule(const char *name) {
131 void *cModule = NULL;
132
133 #ifdef _WINDOWS
134 // Windows stuff here
135 cModule = LoadLibrary(name);
136 #else
137 // Unix stuff here
138 cModule = dlopen(name,RTLD_NOW);
139
140 // Unix dlopen expects an absolute path or the shared object to be in LD_LIBRARY_PATH
141 // Convert the name to an absolute file name
142 if (cModule == NULL) {
143 char absoluteName[MAXPATHLEN];
144 char *absolute = realpath(name,absoluteName);
145
146 if (absolute != NULL) {
147 cModule = dlopen(absolute,RTLD_NOW);
148 }
149 }
150 #endif
151
152 return cModule;
153 }
154
155 ///////////////////////////////////////////////////////////////////////
156 // Funvtion : osModuleError
157 // Description : Get the latest error
158 // Return Value : The error string
159 // Comments :
osModuleError()160 const char *osModuleError() {
161 #ifdef _WINDOWS
162 return NULL;
163 #else
164 return dlerror();
165 #endif
166 }
167
168 ///////////////////////////////////////////////////////////////////////
169 // Function : osUnloadModule
170 // Description : Unload / detach a dll/so file
171 // Return Value : The module handle
172 // Comments :
osUnloadModule(void * cModule)173 void osUnloadModule(void *cModule) {
174 #ifdef _WINDOWS
175 if (cModule != NULL) FreeLibrary((HMODULE) cModule);
176 #else
177 if (cModule != NULL) dlclose((void *) cModule);
178 #endif
179 }
180
181
182 ///////////////////////////////////////////////////////////////////////
183 // Function : osResolve
184 // Description : Resolve a symbol in a dll/so file
185 // Return Value : The module handle
186 // Comments :
osResolve(void * cModule,const char * name)187 void *osResolve(void *cModule,const char *name) {
188 void *result = NULL;
189
190 if (cModule != NULL) {
191 #ifdef _WINDOWS
192 result = GetProcAddress((HMODULE) cModule,name);
193 #else
194 result = dlsym((void *) cModule,name);
195
196 // OSX 10.2.x fix
197 #if defined(__APPLE__) || defined(__APPLE_CC__) // guard against __APPLE__ being undef from ftlk
198 if(result == NULL){
199 char new_name[strlen(name)+2];
200 sprintf(new_name,"_%s",name);
201 result = dlsym((void *) cModule,new_name);
202 }
203 #endif
204
205 #endif
206 }
207
208 return result;
209 }
210
211 ///////////////////////////////////////////////////////////////////////
212 // Function : osEnvironment
213 // Description : Get an environment variable
214 // Return Value : The variable value if found
215 // Comments :
osEnvironment(const char * name)216 char *osEnvironment(const char *name) {
217 return getenv(name);
218 }
219
220 ///////////////////////////////////////////////////////////////////////
221 // Function : osFileExists
222 // Description : Check if a file exists
223 // Return Value : TRUE if it does
224 // Comments :
osFileExists(const char * name)225 int osFileExists(const char *name) {
226 #ifdef _WINDOWS
227 if (_access(name,0) == 0) return TRUE;
228 #else
229 if (access(name,0) == 0) return TRUE;
230 #endif
231 return FALSE;
232 }
233
234
235
236 ///////////////////////////////////////////////////////////////////////
237 // Function : osFixSlashes
238 // Description : Make sure the slashes are right
239 // Return Value : -
240 // Comments :
osFixSlashes(char * st)241 void osFixSlashes(char *st) {
242 for (;*st!='\0';st++) {
243 if ((*st == '\\') || (*st == '/')) *st = OS_DIR_SEPERATOR;
244 }
245 }
246
247
248 ///////////////////////////////////////////////////////////////////////
249 // Function : osTempdir
250 // Description : Create a path to a directory suitable
251 // : for storing temporary files.
252 // Return Value : -
253 // Comments : The directory will end with / or \
254 // : Does not create the directory.
255 // : Path is only unique within this process.
osTempdir(char * result,size_t resultsize)256 void osTempdir(char *result, size_t resultsize) {
257
258 #ifdef _WINDOWS
259 sprintf(result,"PixieTemp_%d\\",GetCurrentProcessId());
260 #elif defined(__APPLE__) || defined(__APPLE_CC__) // guard against __APPLE__ being undef from ftlk
261 FSRef tempRef;
262 char tempDirPath[OS_MAX_PATH_LENGTH];
263 OSErr err = FSFindFolder(kLocalDomain,kTemporaryFolderType,true,&tempRef);
264 if (!err)
265 err = FSRefMakePath(&tempRef,(UInt8*)tempDirPath,sizeof(tempDirPath));
266 if (!err)
267 snprintf(result,resultsize,"%s/PixieTemp_%d/",tempDirPath,getpid());
268 else
269 snprintf(result,resultsize,"/tmp/PixieTemp_%d/",getpid());
270
271 #else
272 // Unix-y
273 const char *tempDirEnv = osEnvironment("TMPDIR");
274 if (!tempDirEnv)
275 tempDirEnv = osEnvironment("TMP");
276 if (tempDirEnv != NULL)
277 snprintf(result,resultsize,"%s/PixieTemp_%d/",tempDirEnv,getpid());
278 else
279 snprintf(result,resultsize,"PixieTemp_%d/",getpid());
280 #endif
281
282 osFixSlashes(result);
283 }
284
285
286 ///////////////////////////////////////////////////////////////////////
287 // Function : osTempname
288 // Description : Create a temporary file
289 // Return Value : -
290 // Comments : The directory must end with / (or \)
osTempname(const char * directory,const char * prefix,char * result)291 void osTempname(const char *directory,const char *prefix,char *result) {
292 #ifdef _WINDOWS
293 // avoid some windows shortcomings by extending count when we
294 // start to get clashes
295 static int i = 0;
296 sprintf(result,"%s%s-%4xXXXXXXXX",directory,prefix,i);
297 while(_mktemp(result) == NULL) {
298 sprintf(result,"%s%s-%4xXXXXXXXX",directory,prefix,i++);
299 }
300 #else
301 sprintf(result,"%s%s-XXXXXXXX",directory,prefix);
302 mktemp(result);
303 #endif
304 }
305
306
307
308
309 ///////////////////////////////////////////////////////////////////////
310 // Function : osCreateDir
311 // Description : Create a directory
312 // Return Value : -
313 // Comments :
osCreateDir(const char * n)314 void osCreateDir(const char *n) {
315 #ifdef _WINDOWS
316 _mkdir(n);
317 #else
318 mkdir(n,S_IRWXU);
319 #endif
320 }
321
322 ///////////////////////////////////////////////////////////////////////
323 // Function : osDeleteDir
324 // Description : Remove a directory
325 // Return Value : -
326 // Comments :
osDeleteDir(const char * n)327 void osDeleteDir(const char *n) {
328 #ifdef _WINDOWS
329 _rmdir(n);
330 #else
331 rmdir(n);
332 #endif
333 }
334
335 ///////////////////////////////////////////////////////////////////////
336 // Function : osDeleteFile
337 // Description : Delete a file
338 // Return Value : -
339 // Comments :
osDeleteFile(const char * n)340 void osDeleteFile(const char *n) {
341 #ifdef _WINDOWS
342 _unlink(n);
343 #else
344 unlink(n);
345 #endif
346 }
347
348
349 ///////////////////////////////////////////////////////////////////////
350 // Function : enumerate
351 // Description : Enumerate the files matching a criteria
352 // Return Value :
353 // Comments :
osEnumerate(const char * name,int (* callback)(const char *,void *),void * userData)354 void osEnumerate(const char *name,int (*callback)(const char *,void *),void *userData) {
355 #ifdef _WINDOWS
356 _finddata_t c_file;
357 intptr_t hFile;
358 char tmp[OS_MAX_PATH_LENGTH];
359 char *tmpp;
360
361 strcpy(tmp,name);
362 osFixSlashes(tmp);
363
364 tmpp = strrchr(tmp,OS_DIR_SEPERATOR);
365 if (tmpp == NULL) {
366 tmpp = tmp;
367 } else {
368 tmpp++;
369 }
370
371 if( (hFile = _findfirst(name, &c_file )) == -1L ) {
372 } else {
373 strcpy(tmpp,c_file.name);
374 if (callback(tmp,userData) == TRUE) {
375 while( _findnext( hFile, &c_file ) == 0 ) {
376 strcpy(tmpp,c_file.name);
377 if (callback(tmp,userData) == FALSE) break;
378 }
379 }
380
381 _findclose( hFile );
382 }
383 #else
384 glob_t globbuf;
385 int i;
386
387 globbuf.gl_offs = 0;
388 glob(name,GLOB_DOOFFS,NULL,&globbuf);
389
390
391 for (i=0;i<globbuf.gl_pathc;i++) {
392 if (callback(globbuf.gl_pathv[i],userData) == FALSE) break;
393 }
394
395 globfree(&globbuf);
396 #endif
397 }
398
399 ///////////////////////////////////////////////////////////////////////
400 // Function : osTime
401 // Description : Get the time
402 // Return Value :
403 // Comments :
osTime()404 float osTime() {
405 struct timeval ti;
406
407 gettimeofday(&ti, NULL);
408
409 return (float) (ti.tv_sec - osStartTimeSec) + (ti.tv_usec - osStartTimeMsec) / 1000000.0f;
410 }
411
412 ///////////////////////////////////////////////////////////////////////
413 // Function : osTime
414 // Description : Get the time
415 // Return Value :
416 // Comments :
osCPUTime()417 float osCPUTime() {
418 return clock() / (float) CLOCKS_PER_SEC;
419 }
420
421 ///////////////////////////////////////////////////////////////////////
422 // Function : osCreateThread
423 // Description : Start a thread
424 // Return Value :
425 // Comments :
osCreateThread(TFun entry,void * d)426 TThread osCreateThread(TFun entry,void *d) {
427 TThread cThread;
428
429 #ifdef _WINDOWS
430 DWORD id;
431
432 cThread = CreateThread(NULL,80000000,entry,d,0,&id);
433 #else
434 pthread_attr_t attr;
435 pthread_attr_init(&attr);
436 pthread_attr_setstacksize(&attr,1024*1024*8);//8MB stack
437 pthread_create(&cThread,&attr,entry,d);
438 pthread_attr_destroy(&attr);
439 //pthread_create(&cThread,NULL,entry,d);
440 #endif
441
442 return cThread;
443 }
444
445 ///////////////////////////////////////////////////////////////////////
446 // Function : osWaitThread
447 // Description : Wait for the termination of a thread
448 // Return Value :
449 // Comments :
osWaitThread(TThread thread)450 int osWaitThread(TThread thread) {
451 #ifdef _WINDOWS
452 WaitForSingleObject(thread,INFINITE);
453 #else
454 return pthread_join(thread,NULL);
455 #endif
456
457 return 0;
458 }
459
460 ///////////////////////////////////////////////////////////////////////
461 // Function : osCreateMutex
462 // Description : Create a mutex
463 // Return Value :
464 // Comments :
osCreateMutex(TMutex & mutex)465 void osCreateMutex(TMutex &mutex) {
466 #ifdef _WINDOWS
467 InitializeCriticalSection(&mutex);
468 #else
469 pthread_mutex_init(&mutex,NULL);
470 #endif
471 }
472
473 ///////////////////////////////////////////////////////////////////////
474 // Function : osDeleteMutex
475 // Description : Delete a mutex
476 // Return Value :
477 // Comments :
osDeleteMutex(TMutex & mutex)478 void osDeleteMutex(TMutex &mutex) {
479 #ifdef _WINDOWS
480 DeleteCriticalSection(&mutex);
481 #else
482 pthread_mutex_destroy(&mutex);
483 #endif
484 }
485
486 ///////////////////////////////////////////////////////////////////////
487 // Function : osCreateSemaphore
488 // Description : Create a semaphere
489 // Return Value :
490 // Comments :
osCreateSemaphore(TSemaphore & sem,int count)491 void osCreateSemaphore(TSemaphore &sem,int count) {
492 #ifdef _WINDOWS
493 sem = CreateSemaphore(NULL,0,count,NULL);
494 #else
495 sem_init(&sem,PTHREAD_PROCESS_PRIVATE,count);
496 #endif
497 }
498
499 ///////////////////////////////////////////////////////////////////////
500 // Function : osDeleteMutex
501 // Description : Delete a mutex
502 // Return Value :
503 // Comments :
osDeleteSemaphore(TSemaphore & sem)504 void osDeleteSemaphore(TSemaphore &sem) {
505 #ifdef _WINDOWS
506 CloseHandle(sem);
507 #else
508 sem_destroy(&sem);
509 #endif
510 }
511
512
513 ///////////////////////////////////////////////////////////////////////
514 // Function : osProcessEscapes
515 // Description : Process the escape characters in a string
516 // Return Value :
517 // Comments :
osProcessEscapes(char * str)518 void osProcessEscapes(char *str) {
519 int i,n,j;
520
521 n = (int) strlen(str);
522 for (i=0;i<n;i++) {
523 if (str[i] == '\\') {
524 switch(str[i+1]) {
525 case 'n':
526 str[i] = '\n';
527 break;
528 case 't':
529 str[i] = '\t';
530 break;
531 case 'r':
532 str[i] = '\r';
533 break;
534 case '\\':
535 str[i] = '\\';
536 break;
537 default:
538 break;
539 }
540
541 j = i+2;
542 do {
543 str[j-1] = str[j];
544 j++;
545 } while(str[j] != '\0');
546 n--;
547 i++;
548 }
549 }
550 str[i] = '\0';
551 }
552
553 ///////////////////////////////////////////////////////////////////////
554 // Function : osAvailableCPUs
555 // Description : Get number of CPUs available
556 // Return Value : Number of available CPUs or -1 if unknown
557 // Comments : See <http://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine>
osAvailableCPUs()558 int osAvailableCPUs() {
559
560 #if defined(WIN32)
561 SYSTEM_INFO sys_info;
562 GetSystemInfo(&sys_info);
563 return sys_info.dwNumberOfProcessors;
564
565 #elif defined(CTL_HW)
566 // BSD, Mac OS X
567 int ncpu = 0;
568 int mib[2];
569 size_t sz = sizeof(ncpu);
570 mib[0] = CTL_HW;
571 #ifdef HW_AVAILCPU
572 mib[1] = HW_AVAILCPU;
573 #else
574 mib[1] = HW_NCPU;
575 #endif
576 if(sysctl(mib, 2, &ncpu, &sz, NULL, 0) == -1)
577 return ncpu;
578
579 #elif defined(_SC_NPROCESSORS_ONLN)
580 // Linux, AIX, Solaris
581 return sysconf( _SC_NPROCESSORS_ONLN );
582
583 #elif defined(MPC_GETNUMSPUS)
584 // HP-UX
585 return mpctl(MPC_GETNUMSPUS, NULL, NULL);
586
587 #elif defined(_SC_NPROC_ONLN)
588 // IRIX
589 return sysconf( _SC_NPROC_ONLN );
590 #endif
591
592 return -1;
593 }
594
595
596