/*
    thread functions
    Copyright (C) 2011 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#include <libziaint.h>

#include <zthread.h>

#include <zdebug.h>
#include <zfile.h>
#include <zstr.h>

#ifdef Z_HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef Z_MSC_MINGW
#include <windows.h>
#endif

#ifdef Z_HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif

#ifdef Z_MSC //_MINGW  error: conflicting types for 'sleep'
unsigned int sleep(unsigned int sec){
	Sleep(sec * 1000);
    return 0; // elapsed
}
#endif

#ifdef Z_MSC
unsigned int usleep(unsigned int usec){
    Sleep(usec / 1000); 
    return 0; // success
}
#endif
																	
#ifndef Z_HAVE_G_THREAD_TRY_NEW
GThread *g_thread_try_new(const gchar *name, GThreadFunc func, gpointer data, GError **error){
    return g_thread_create(func, data, TRUE, error); 
}
#endif


#ifdef Z_MSC_MINGW
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
   DWORD dwType; // Must be 0x1000.
   LPCSTR szName; // Pointer to name (in user addr space).
   DWORD dwThreadID; // Thread ID (-1=caller thread).
   DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
#endif


// under linux use ps Hc to show thread name
void zg_thread_set_name(char* name)
{
#ifdef Z_MSC
	const DWORD MS_VC_EXCEPTION=0x406D1388;

   THREADNAME_INFO info;
   info.dwType = 0x1000;
   info.szName = name;
   info.dwThreadID = -1;
   info.dwFlags = 0;

   __try
   {
      RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
   }
   __except(EXCEPTION_EXECUTE_HANDLER)
   {
   }
/*#elif defined(Z_HAVE_PTHREAD_SETNAME_NP)     TODO check on glibc 2.12
	pthread_setname_np(pthread_self(), name);*/
#elif defined(Z_HAVE_SYS_PRCTL_H)
   prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
//    dbg("prctl(PR_SET_NAME, '%s')=%d\n", name, ret);
#else
    
#endif
}



#ifdef Z_UNIX_ANDROID
int z_cpu_cores(){
    int ret = 0;
    GString *gs = g_string_new("");
    FILE *f = fopen("/proc/cpuinfo", "rt");
    if (f == NULL) return 1;

    while (zfile_fgets(gs, f, 1)){
        if (zstr_begins_with(gs->str, "processor", 1)) ret++;
    }
    fclose(f);
    g_string_free(gs, TRUE);
    return ret;
}
#endif

#ifdef Z_MSC_MINGW
int z_cpu_cores(){
    SYSTEM_INFO si;

    GetSystemInfo(&si);
    return si.dwNumberOfProcessors;
}
#endif

#ifdef Z_MSC_MINGW
int zg_thread_set_priority(int priority){
	int ret;
	HANDLE thread = GetCurrentThread();

	ret = SetThreadPriority(thread, priority);

	return ret == 0 ? -1 : 0;
}
#endif

#ifdef Z_UNIX_ANDROID
int zg_thread_set_priority(int priority){
	return 0;

}
#endif
