int main(int argc, char *argv[]) { START(argc, argv, "vmem_multiple_pools"); if (argc < 4) UT_FATAL("usage: %s directory npools nthreads", argv[0]); dir = argv[1]; npools = ATOU(argv[2]); unsigned nthreads = ATOU(argv[3]); UT_OUT("create %d pools in %d thread(s)", npools, nthreads); const unsigned mem_pools_size = (npools / 2 + npools % 2) * nthreads; mem_pools = MALLOC(mem_pools_size * sizeof(char *)); pools = CALLOC(npools * nthreads, sizeof(VMEM *)); os_thread_t *threads = CALLOC(nthreads, sizeof(os_thread_t)); UT_ASSERTne(threads, NULL); unsigned *pool_idx = CALLOC(nthreads, sizeof(pool_idx[0])); UT_ASSERTne(pool_idx, NULL); for (unsigned pool_id = 0; pool_id < mem_pools_size; ++pool_id) { /* allocate memory for function vmem_create_in_region() */ mem_pools[pool_id] = MMAP_ANON_ALIGNED(VMEM_MIN_POOL, 4 << 20); } /* create and destroy pools multiple times */ for (unsigned t = 0; t < nthreads; t++) { pool_idx[t] = npools * t; PTHREAD_CREATE(&threads[t], NULL, thread_func, &pool_idx[t]); } for (unsigned t = 0; t < nthreads; t++) PTHREAD_JOIN(&threads[t], NULL); for (unsigned pool_id = 0; pool_id < npools * nthreads; ++pool_id) { if (pools[pool_id] != NULL) { vmem_delete(pools[pool_id]); pools[pool_id] = NULL; } } FREE(mem_pools); FREE(pools); FREE(threads); FREE(pool_idx); DONE(NULL); }
int main(int argc, char *argv[]) { START(argc, argv, "cto_multiple_pools"); if (argc < 4) UT_FATAL("usage: %s directory mode npools nthreads", argv[0]); Dir = argv[1]; char mode = argv[2][0]; Npools = ATOU(argv[3]); unsigned nthreads = ATOU(argv[4]); UT_OUT("create %d pools in %d thread(s)", Npools, nthreads); Pools = CALLOC(Npools * nthreads, sizeof(Pools[0])); Threads = CALLOC(nthreads, sizeof(Threads[0])); Pool_idx = CALLOC(nthreads, sizeof(Pool_idx[0])); switch (mode) { case 'o': test_open(nthreads); break; case 'c': test_create(nthreads); break; default: UT_FATAL("unknown mode"); } FREE(Pools); FREE(Threads); FREE(Pool_idx); DONE(NULL); }
/** * Entry point */ int main(int argc, char **argv) { static const char* cmds[] = { "b", "buffer", "1", SETTINGR("Buffer size [KW], default: ",COLLECT_BUFSIZE), "d", "data", "1", SETTINGR("Data cache size [KB], with fallback to: ", GENERIC_DCACHE ), "i", "inst", "1", SETTINGR("Instruction cache size [KB], with fallback to: ", GENERIC_ICACHE), "f", "file", "1", "Sample output file, default: '" OUTPUT_DEFAULT "', '-' for stdout", "F", "Foreground", "0", "Run daemon in foreground", "r", "run", "1", "0=daemon, 1=config info, >1=<r>KB sample", "n", "number", "1", "Output size in [k|m|g|t] bytes, 0 = unlimited to stdout", "o", "onlinetest", "1", "[t<x>][c<x>] x=[a[n][w]][b[w]] 't'ot, 'c'ontinuous, default: ta8b", "p", "pidfile", "1", "daemon pidfile, default: " PID_DEFAULT , "s", "source", "1", "Injection source file, default: '" INPUT_DEFAULT "', '-' for stdin", "t", "threads", "1", "Number of threads", "v", "verbose", "1", "Verbose mask 0=none,1=summary,2=retries,4=timing,8=loop,16=code,32=test", "w", "write", "1", "Set write_wakeup_threshold [bits]", "h", "help", "0", "This help" }; static int nopts = sizeof(cmds)/(4*sizeof(char *)); struct option long_options[nopts+1]; char short_options[1+nopts*2]; int c,i,j; H_UINT bufct, bufrem, ierr; H_PARAMS cmd; if (havege_version(HAVEGE_PREP_VERSION)==NULL) error_exit("version conflict %s!=%s", HAVEGE_PREP_VERSION, havege_version(NULL)); #if NO_DAEMON==1 params->setup |= RUN_AS_APP; #endif #ifdef RAW_IN_ENABLE #define DIAG_USAGE2 SETTINGL("=inject ticks,", DIAG_RUN_INJECT)\ SETTINGL("=inject data", DIAG_RUN_TEST) params->setup |= INJECT | RUN_AS_APP; #else #define DIAG_USAGE2 "" #endif #ifdef RAW_OUT_ENABLE #define DIAG_USAGE1 SETTINGL("=capture,", DIAG_RUN_CAPTURE) params->setup |= CAPTURE | RUN_AS_APP; #else #define DIAG_USAGE1 "" #endif #if NUMBER_CORES>1 params->setup |= MULTI_CORE; #endif #ifdef SIGHUP signal(SIGHUP, tidy_exit); #endif signal(SIGINT, tidy_exit); signal(SIGTERM, tidy_exit); strcpy(short_options,""); bufct = bufrem = 0; /** * Build options */ for(i=j=0;j<(nopts*4);j+=4) { switch(cmds[j][0]) { case 'o': #ifdef ONLINE_TESTS_ENABLE break; #else continue; #endif case 'r': #if defined(RAW_IN_ENABLE) || defined (RAW_OUT_ENABLE) if (0!=(params->setup & (INJECT|CAPTURE))) { params->daemon = "havege_diagnostic"; cmds[j+3] = "run level, 0=diagnostic off,1=config info," DIAG_USAGE1 DIAG_USAGE2 ; } else #endif if (0!=(params->setup & RUN_AS_APP)) continue; break; case 's': if (0 == (params->setup & INJECT)) continue; break; case 't': if (0 == (params->setup & MULTI_CORE)) continue; break; case 'p': case 'w': case 'F': if (0 !=(params->setup & RUN_AS_APP)) continue; break; } long_options[i].name = cmds[j+1]; long_options[i].has_arg = atoi(cmds[j+2]); long_options[i].flag = NULL; long_options[i].val = cmds[j][0]; strcat(short_options,cmds[j]); if (long_options[i].has_arg!=0) strcat(short_options,":"); i += 1; } memset(&long_options[i], 0, sizeof(struct option)); do { c = getopt_long (argc, argv, short_options, long_options, NULL); switch(c) { case 'F': params->setup |= RUN_IN_FG; params->foreground = 1; break; case 'b': params->buffersz = ATOU(optarg) * 1024; if (params->buffersz<4) error_exit("invalid size %s", optarg); break; case 'd': params->d_cache = ATOU(optarg); break; case 'i': params->i_cache = ATOU(optarg); break; case 'f': params->sample_out = optarg; if (strcmp(optarg,"-") == 0 ) params->setup |= USE_STDOUT; break; case 'n': if (get_runsize(&bufct, &bufrem, optarg)) error_exit("invalid count: %s", optarg); params->setup |= RUN_AS_APP|RANGE_SPEC; if (bufct==0 && bufrem==0) params->setup |= USE_STDOUT; /* ugly but documented behavior! */ break; case 'o': params->tests_config = optarg; break; case 'p': params->pid_file = optarg; break; case 'r': params->run_level = ATOU(optarg); if (params->run_level != 0) params->setup |= RUN_AS_APP; break; case 's': params->sample_in = optarg; break; case 't': params->ncores = ATOU(optarg); if (params->ncores > NUMBER_CORES) error_exit("invalid thread count: %s", optarg); break; case 'v': params->verbose = ATOU(optarg); break; case 'w': params->setup |= SET_LWM; params->low_water = ATOU(optarg); break; case '?': case 'h': usage(0, nopts, long_options, cmds); case -1: break; } } while (c!=-1); if (params->tests_config == 0) params->tests_config = (0 != (params->setup & RUN_AS_APP))? TESTS_DEFAULT_APP : TESTS_DEFAULT_RUN; memset(&cmd, 0, sizeof(H_PARAMS)); cmd.collectSize = params->buffersz; cmd.icacheSize = params->i_cache; cmd.dcacheSize = params->d_cache; cmd.options = params->verbose & 0xff; cmd.nCores = params->ncores; cmd.testSpec = params->tests_config; cmd.msg_out = print_msg; if (0 != (params->setup & RUN_AS_APP)) { cmd.ioSz = APP_BUFF_SIZE * sizeof(H_UINT); if (params->verbose!=0 && 0==(params->setup & RANGE_SPEC)) params->run_level = 1; } #ifndef NO_DAEMON else { poolSize = get_poolsize(); i = (poolSize + 7)/8 * sizeof(H_UINT); cmd.ioSz = sizeof(struct rand_pool_info) + i *sizeof(H_UINT); } #endif if (0 != (params->verbose & H_DEBUG_TIME)) cmd.metering = show_meterInfo; if (0 !=(params->setup & CAPTURE) && 0 != (params->run_level == DIAG_RUN_CAPTURE)) cmd.options |= H_DEBUG_RAW_OUT; #ifdef RAW_IN_ENABLE if (0 !=(params->setup & INJECT) && 0 != (params->run_level & (DIAG_RUN_INJECT|DIAG_RUN_TEST))) { if (strcmp(params->sample_in,"-") == 0 ) fd_in = stdin; else fd_in = fopen(params->sample_in, "rb"); if (NULL == fd_in) error_exit("Unable to open: %s", params->sample_in); cmd.injection = injectFile; if (params->run_level==DIAG_RUN_INJECT) cmd.options |= H_DEBUG_RAW_IN; else if (params->run_level==DIAG_RUN_TEST) cmd.options |= H_DEBUG_TEST_IN; else usage(1, nopts, long_options, cmds); } #endif handle = havege_create(&cmd); ierr = handle==NULL? H_NOHANDLE : handle->error; switch(ierr) { case H_NOERR: break; case H_NOTESTSPEC: error_exit("unrecognized test setup: %s", cmd.testSpec); break; default: error_exit("Couldn't initialize haveged (%d)", ierr); } if (0 != (params->setup & RUN_AS_APP)) { if (params->run_level==1) anchor_info(handle); else if (0==(params->setup&(INJECT|CAPTURE))) { /* must specify range with --nunber or --run > 1 but not both */ if (params->run_level>1) { if (0==(params->setup&RANGE_SPEC)) { /* --run specified */ bufct = params->run_level/sizeof(H_UINT); bufrem = (params->run_level%sizeof(H_UINT))*1024; } else usage(2, nopts, long_options, cmds); /* both specified */ } else if (0==(params->setup&RANGE_SPEC)) usage(3,nopts, long_options, cmds); /* neither specified */ else if (0==(params->setup&USE_STDOUT)&&(bufct+bufrem)==0) usage(4, nopts, long_options, cmds); /* only with stdout */ run_app(handle, bufct, bufrem); } else if (0==(params->setup&USE_STDOUT)&&(bufct+bufrem)==0) usage(5, nopts, long_options, cmds); /* only with stdout */ else run_app(handle, bufct, bufrem); } #ifndef NO_DAEMON else run_daemon(handle); #endif havege_destroy(handle); exit(0); }
ResultType Line::RegWrite(DWORD aValueType, HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName, LPTSTR aValue) // If aValueName is the empty string, the key's default value is used. { HKEY hRegKey; DWORD dwRes, dwBuf; // My: Seems safest to keep the limit just below 64K in case Win95 has problems with larger values. TCHAR szRegBuffer[65535], *buf; // Only allow writing of 64Kb to a key for Win9x, which is all it supports. #define SET_REG_BUF \ if (g_os.IsWin9x())\ {\ tcslcpy(szRegBuffer, aValue, sizeof(szRegBuffer));\ buf = szRegBuffer;\ }\ else\ buf = aValue; LONG result; if (!aRootKey || aValueType == REG_NONE || aValueType == REG_SUBKEY) // Can't write to these. { result = ERROR_INVALID_PARAMETER; // Indicate the error. goto finish; } // Open/Create the registry key // The following works even on root keys (i.e. blank subkey), although values can't be created/written to // HKCU's root level, perhaps because it's an alias for a subkey inside HKEY_USERS. Even when RegOpenKeyEx() // is used on HKCU (which is probably redundant since it's a pre-opened key?), the API can't create values // there even though RegEdit can. result = RegCreateKeyEx(aRootKey, aRegSubkey, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dwRes); if (result != ERROR_SUCCESS) goto finish; // Write the registry differently depending on type of variable we are writing switch (aValueType) { case REG_SZ: SET_REG_BUF result = RegSetValueEx(hRegKey, aValueName, 0, REG_SZ, (CONST BYTE *)buf, (DWORD)(_tcslen(buf)+1) * sizeof(TCHAR)); break; case REG_EXPAND_SZ: SET_REG_BUF result = RegSetValueEx(hRegKey, aValueName, 0, REG_EXPAND_SZ, (CONST BYTE *)buf, (DWORD)(_tcslen(buf)+1) * sizeof(TCHAR)); break; case REG_MULTI_SZ: { // Don't allow values over 64K for this type because aValue might not be a writable // string, and we would need to write to it to temporarily change the newline delimiters // into zero-delimiters. Even if we were to require callers to give us a modifiable string, // its capacity be 1 byte too small to handle the double termination that's needed // (i.e. if the last item in the list happens to not end in a newline): tcslcpy(szRegBuffer, aValue, _countof(szRegBuffer) - 1); // -1 to leave space for a 2nd terminator. // Double-terminate: size_t length = _tcslen(szRegBuffer); szRegBuffer[length + 1] = '\0'; // Remove any final newline the user may have provided since we don't want the length // to include it when calling RegSetValueEx() -- it would be too large by 1: if (length > 0 && szRegBuffer[length - 1] == '\n') szRegBuffer[--length] = '\0'; // Replace the script's delimiter char with the zero-delimiter needed by RegSetValueEx(): for (LPTSTR cp = szRegBuffer; *cp; ++cp) if (*cp == '\n') *cp = '\0'; result = RegSetValueEx(hRegKey, aValueName, 0, REG_MULTI_SZ, (CONST BYTE *)szRegBuffer , (DWORD)(length ? length + 2 : 0) * sizeof(TCHAR)); break; } case REG_DWORD: if (*aValue) dwBuf = ATOU(aValue); // Changed to ATOU() for v1.0.24 so that hex values are supported. else // Default to 0 when blank. dwBuf = 0; result = RegSetValueEx(hRegKey, aValueName, 0, REG_DWORD, (CONST BYTE *)&dwBuf, sizeof(dwBuf)); break; case REG_BINARY: { int nLen = (int)_tcslen(aValue); // String length must be a multiple of 2 if (nLen % 2) { result = ERROR_INVALID_PARAMETER; break; } // Really crappy hex conversion int j = 0, i = 0, nVal, nMult; LPBYTE pRegBuffer = (LPBYTE) szRegBuffer; while (i < nLen && j < sizeof(szRegBuffer)) { nVal = 0; for (nMult = 16; nMult >= 0; nMult = nMult - 15) { if (aValue[i] >= '0' && aValue[i] <= '9') nVal += (aValue[i] - '0') * nMult; else if (aValue[i] >= 'A' && aValue[i] <= 'F') nVal += (((aValue[i] - 'A'))+10) * nMult; else if (aValue[i] >= 'a' && aValue[i] <= 'f') nVal += (((aValue[i] - 'a'))+10) * nMult; else { RegCloseKey(hRegKey); result = ERROR_INVALID_PARAMETER; goto finish; } ++i; } pRegBuffer[j++] = (char)nVal; } result = RegSetValueEx(hRegKey, aValueName, 0, REG_BINARY, pRegBuffer, (DWORD)j); break; } default: result = ERROR_INVALID_PARAMETER; // Anything other than ERROR_SUCCESS. break; } // switch() RegCloseKey(hRegKey); // Additionally, fall through to below: finish: return SetErrorsOrThrow(result != ERROR_SUCCESS, result); } // RegWrite()
int WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // Init any globals not in "struct g" that need it: g_hInstance = hInstance; InitializeCriticalSection(&g_CriticalRegExCache); // v1.0.45.04: Must be done early so that it's unconditional, so that DeleteCriticalSection() in the script destructor can also be unconditional (deleting when never initialized can crash, at least on Win 9x). if (!GetCurrentDirectory(_countof(g_WorkingDir), g_WorkingDir)) // Needed for the FileSelectFile() workaround. *g_WorkingDir = '\0'; // Unlike the below, the above must not be Malloc'd because the contents can later change to something // as large as MAX_PATH by means of the SetWorkingDir command. g_WorkingDirOrig = SimpleHeap::Malloc(g_WorkingDir); // Needed by the Reload command. // Set defaults, to be overridden by command line args we receive: bool restart_mode = false; #ifndef AUTOHOTKEYSC #ifdef _DEBUG TCHAR *script_filespec = _T("Test\\Test.ahk"); #else TCHAR *script_filespec = NULL; // Set default as "unspecified/omitted". #endif #endif // The problem of some command line parameters such as /r being "reserved" is a design flaw (one that // can't be fixed without breaking existing scripts). Fortunately, I think it affects only compiled // scripts because running a script via AutoHotkey.exe should avoid treating anything after the // filename as switches. This flaw probably occurred because when this part of the program was designed, // there was no plan to have compiled scripts. // // Examine command line args. Rules: // Any special flags (e.g. /force and /restart) must appear prior to the script filespec. // The script filespec (if present) must be the first non-backslash arg. // All args that appear after the filespec are considered to be parameters for the script // and will be added as variables %1% %2% etc. // The above rules effectively make it impossible to autostart AutoHotkey.ini with parameters // unless the filename is explicitly given (shouldn't be an issue for 99.9% of people). TCHAR var_name[32], *param; // Small size since only numbers will be used (e.g. %1%, %2%). Var *var; bool switch_processing_is_complete = false; int script_param_num = 1; for (int i = 1; i < __argc; ++i) // Start at 1 because 0 contains the program name. { param = __targv[i]; // For performance and convenience. if (switch_processing_is_complete) // All args are now considered to be input parameters for the script. { if ( !(var = g_script.FindOrAddVar(var_name, _stprintf(var_name, _T("%d"), script_param_num))) ) return CRITICAL_ERROR; // Realistically should never happen. var->Assign(param); ++script_param_num; } // Insist that switches be an exact match for the allowed values to cut down on ambiguity. // For example, if the user runs "CompiledScript.exe /find", we want /find to be considered // an input parameter for the script rather than a switch: else if (!_tcsicmp(param, _T("/R")) || !_tcsicmp(param, _T("/restart"))) restart_mode = true; else if (!_tcsicmp(param, _T("/F")) || !_tcsicmp(param, _T("/force"))) g_ForceLaunch = true; else if (!_tcsicmp(param, _T("/ErrorStdOut"))) g_script.mErrorStdOut = true; #ifndef AUTOHOTKEYSC // i.e. the following switch is recognized only by AutoHotkey.exe (especially since recognizing new switches in compiled scripts can break them, unlike AutoHotkey.exe). else if (!_tcsicmp(param, _T("/iLib"))) // v1.0.47: Build an include-file so that ahk2exe can include library functions called by the script. { ++i; // Consume the next parameter too, because it's associated with this one. if (i >= __argc) // Missing the expected filename parameter. return CRITICAL_ERROR; // For performance and simplicity, open/create the file unconditionally and keep it open until exit. g_script.mIncludeLibraryFunctionsThenExit = new TextFile; if (!g_script.mIncludeLibraryFunctionsThenExit->Open(__targv[i], TextStream::WRITE | TextStream::EOL_CRLF | TextStream::BOM_UTF8, CP_UTF8)) // Can't open the temp file. return CRITICAL_ERROR; } else if (!_tcsnicmp(param, _T("/CP"), 3)) // /CPnnn { // Default codepage for the script file, NOT the default for commands used by it. g_DefaultScriptCodepage = ATOU(param + 3); } #endif #ifdef CONFIG_DEBUGGER // Allow a debug session to be initiated by command-line. else if (!g_Debugger.IsConnected() && !_tcsnicmp(param, _T("/Debug"), 6) && (param[6] == '\0' || param[6] == '=')) { if (param[6] == '=') { param += 7; LPTSTR c = _tcsrchr(param, ':'); if (c) { StringTCharToChar(param, g_DebuggerHost, (int)(c-param)); StringTCharToChar(c + 1, g_DebuggerPort); } else { StringTCharToChar(param, g_DebuggerHost); g_DebuggerPort = "9000"; } } else { g_DebuggerHost = "localhost"; g_DebuggerPort = "9000"; } // The actual debug session is initiated after the script is successfully parsed. } #endif else // since this is not a recognized switch, the end of the [Switches] section has been reached (by design). { switch_processing_is_complete = true; // No more switches allowed after this point. #ifdef AUTOHOTKEYSC --i; // Make the loop process this item again so that it will be treated as a script param. #else script_filespec = param; // The first unrecognized switch must be the script filespec, by design. #endif } } #ifndef AUTOHOTKEYSC if (script_filespec)// Script filename was explicitly specified, so check if it has the special conversion flag. { size_t filespec_length = _tcslen(script_filespec); if (filespec_length >= CONVERSION_FLAG_LENGTH) { LPTSTR cp = script_filespec + filespec_length - CONVERSION_FLAG_LENGTH; // Now cp points to the first dot in the CONVERSION_FLAG of script_filespec (if it has one). if (!_tcsicmp(cp, CONVERSION_FLAG)) return Line::ConvertEscapeChar(script_filespec); } } #endif // Like AutoIt2, store the number of script parameters in the script variable %0%, even if it's zero: if ( !(var = g_script.FindOrAddVar(_T("0"))) ) return CRITICAL_ERROR; // Realistically should never happen. var->Assign(script_param_num - 1); global_init(*g); // Set defaults prior to the below, since below might override them for AutoIt2 scripts. // Set up the basics of the script: #ifdef AUTOHOTKEYSC if (g_script.Init(*g, _T(""), restart_mode) != OK) #else if (g_script.Init(*g, script_filespec, restart_mode) != OK) // Set up the basics of the script, using the above. #endif return CRITICAL_ERROR; // Set g_default now, reflecting any changes made to "g" above, in case AutoExecSection(), below, // never returns, perhaps because it contains an infinite loop (intentional or not): CopyMemory(&g_default, g, sizeof(global_struct)); // Could use CreateMutex() but that seems pointless because we have to discover the // hWnd of the existing process so that we can close or restart it, so we would have // to do this check anyway, which serves both purposes. Alt method is this: // Even if a 2nd instance is run with the /force switch and then a 3rd instance // is run without it, that 3rd instance should still be blocked because the // second created a 2nd handle to the mutex that won't be closed until the 2nd // instance terminates, so it should work ok: //CreateMutex(NULL, FALSE, script_filespec); // script_filespec seems a good choice for uniqueness. //if (!g_ForceLaunch && !restart_mode && GetLastError() == ERROR_ALREADY_EXISTS) #ifdef AUTOHOTKEYSC UINT load_result = g_script.LoadFromFile(); #else UINT load_result = g_script.LoadFromFile(script_filespec == NULL); #endif if (load_result == LOADING_FAILED) // Error during load (was already displayed by the function call). return CRITICAL_ERROR; // Should return this value because PostQuitMessage() also uses it. if (!load_result) // LoadFromFile() relies upon us to do this check. No script was loaded or we're in /iLib mode, so nothing more to do. return 0; // Unless explicitly set to be non-SingleInstance via SINGLE_INSTANCE_OFF or a special kind of // SingleInstance such as SINGLE_INSTANCE_REPLACE and SINGLE_INSTANCE_IGNORE, persistent scripts // and those that contain hotkeys/hotstrings are automatically SINGLE_INSTANCE_PROMPT as of v1.0.16: if (g_AllowOnlyOneInstance == ALLOW_MULTI_INSTANCE && IS_PERSISTENT) g_AllowOnlyOneInstance = SINGLE_INSTANCE_PROMPT; HWND w_existing = NULL; UserMessages reason_to_close_prior = (UserMessages)0; if (g_AllowOnlyOneInstance && g_AllowOnlyOneInstance != SINGLE_INSTANCE_OFF && !restart_mode && !g_ForceLaunch) { // Note: the title below must be constructed the same was as is done by our // CreateWindows(), which is why it's standardized in g_script.mMainWindowTitle: if (w_existing = FindWindow(WINDOW_CLASS_MAIN, g_script.mMainWindowTitle)) { if (g_AllowOnlyOneInstance == SINGLE_INSTANCE_IGNORE) return 0; if (g_AllowOnlyOneInstance != SINGLE_INSTANCE_REPLACE) if (MsgBox(_T("An older instance of this script is already running. Replace it with this") _T(" instance?\nNote: To avoid this message, see #SingleInstance in the help file.") , MB_YESNO, g_script.mFileName) == IDNO) return 0; // Otherwise: reason_to_close_prior = AHK_EXIT_BY_SINGLEINSTANCE; } } if (!reason_to_close_prior && restart_mode) if (w_existing = FindWindow(WINDOW_CLASS_MAIN, g_script.mMainWindowTitle)) reason_to_close_prior = AHK_EXIT_BY_RELOAD; if (reason_to_close_prior) { // Now that the script has been validated and is ready to run, close the prior instance. // We wait until now to do this so that the prior instance's "restart" hotkey will still // be available to use again after the user has fixed the script. UPDATE: We now inform // the prior instance of why it is being asked to close so that it can make that reason // available to the OnExit subroutine via a built-in variable: ASK_INSTANCE_TO_CLOSE(w_existing, reason_to_close_prior); //PostMessage(w_existing, WM_CLOSE, 0, 0); // Wait for it to close before we continue, so that it will deinstall any // hooks and unregister any hotkeys it has: int interval_count; for (interval_count = 0; ; ++interval_count) { Sleep(20); // No need to use MsgSleep() in this case. if (!IsWindow(w_existing)) break; // done waiting. if (interval_count == 100) { // This can happen if the previous instance has an OnExit subroutine that takes a long // time to finish, or if it's waiting for a network drive to timeout or some other // operation in which it's thread is occupied. if (MsgBox(_T("Could not close the previous instance of this script. Keep waiting?"), 4) == IDNO) return CRITICAL_ERROR; interval_count = 0; } } // Give it a small amount of additional time to completely terminate, even though // its main window has already been destroyed: Sleep(100); } // Call this only after closing any existing instance of the program, // because otherwise the change to the "focus stealing" setting would never be undone: SetForegroundLockTimeout(); // Create all our windows and the tray icon. This is done after all other chances // to return early due to an error have passed, above. if (g_script.CreateWindows() != OK) return CRITICAL_ERROR; // At this point, it is nearly certain that the script will be executed. // v1.0.48.04: Turn off buffering on stdout so that "FileAppend, Text, *" will write text immediately // rather than lazily. This helps debugging, IPC, and other uses, probably with relatively little // impact on performance given the OS's built-in caching. I looked at the source code for setvbuf() // and it seems like it should execute very quickly. Code size seems to be about 75 bytes. setvbuf(stdout, NULL, _IONBF, 0); // Must be done PRIOR to writing anything to stdout. if (g_MaxHistoryKeys && (g_KeyHistory = (KeyHistoryItem *)malloc(g_MaxHistoryKeys * sizeof(KeyHistoryItem)))) ZeroMemory(g_KeyHistory, g_MaxHistoryKeys * sizeof(KeyHistoryItem)); // Must be zeroed. //else leave it NULL as it was initialized in globaldata. // MSDN: "Windows XP: If a manifest is used, InitCommonControlsEx is not required." // Therefore, in case it's a high overhead call, it's not done on XP or later: if (!g_os.IsWinXPorLater()) { // Since InitCommonControls() is apparently incapable of initializing DateTime and MonthCal // controls, InitCommonControlsEx() must be called. But since Ex() requires comctl32.dll // 4.70+, must get the function's address dynamically in case the program is running on // Windows 95/NT without the updated DLL (otherwise the program would not launch at all). typedef BOOL (WINAPI *MyInitCommonControlsExType)(LPINITCOMMONCONTROLSEX); MyInitCommonControlsExType MyInitCommonControlsEx = (MyInitCommonControlsExType) GetProcAddress(GetModuleHandle(_T("comctl32")), "InitCommonControlsEx"); // LoadLibrary shouldn't be necessary because comctl32 in linked by compiler. if (MyInitCommonControlsEx) { INITCOMMONCONTROLSEX icce; icce.dwSize = sizeof(INITCOMMONCONTROLSEX); icce.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES; // ICC_WIN95_CLASSES is equivalent to calling InitCommonControls(). MyInitCommonControlsEx(&icce); } else // InitCommonControlsEx not available, so must revert to non-Ex() to make controls work on Win95/NT4. InitCommonControls(); } #ifdef CONFIG_DEBUGGER // Initiate debug session now if applicable. if (!g_DebuggerHost.IsEmpty() && g_Debugger.Connect(g_DebuggerHost, g_DebuggerPort) == DEBUGGER_E_OK) { g_Debugger.ProcessCommands(); } #endif // Activate the hotkeys, hotstrings, and any hooks that are required prior to executing the // top part (the auto-execute part) of the script so that they will be in effect even if the // top part is something that's very involved and requires user interaction: Hotkey::ManifestAllHotkeysHotstringsHooks(); // We want these active now in case auto-execute never returns (e.g. loop) g_script.mIsReadyToExecute = true; // This is done only after the above to support error reporting in Hotkey.cpp. Var *clipboard_var = g_script.FindOrAddVar(_T("Clipboard")); // Add it if it doesn't exist, in case the script accesses "Clipboard" via a dynamic variable. if (clipboard_var) // This is done here rather than upon variable creation speed up runtime/dynamic variable creation. // Since the clipboard can be changed by activity outside the program, don't read-cache its contents. // Since other applications and the user should see any changes the program makes to the clipboard, // don't write-cache it either. clipboard_var->DisableCache(); // Run the auto-execute part at the top of the script (this call might never return): if (!g_script.AutoExecSection()) // Can't run script at all. Due to rarity, just abort. return CRITICAL_ERROR; // REMEMBER: The call above will never return if one of the following happens: // 1) The AutoExec section never finishes (e.g. infinite loop). // 2) The AutoExec function uses the Exit or ExitApp command to terminate the script. // 3) The script isn't persistent and its last line is reached (in which case an ExitApp is implicit). // Call it in this special mode to kick off the main event loop. // Be sure to pass something >0 for the first param or it will // return (and we never want this to return): MsgSleep(SLEEP_INTERVAL, WAIT_FOR_MESSAGES); return 0; // Never executed; avoids compiler warning. }
int main(int argc, char *argv[]) { START(argc, argv, "obj_direct"); if (argc != 3) UT_FATAL("usage: %s [directory] [# of pools]", argv[0]); unsigned npools = ATOU(argv[2]); const char *dir = argv[1]; int r; os_mutex_init(&lock1); os_mutex_init(&lock2); os_cond_init(&sync_cond1); os_cond_init(&sync_cond2); cond1 = cond2 = 0; PMEMobjpool **pops = MALLOC(npools * sizeof(PMEMobjpool *)); UT_ASSERTne(pops, NULL); size_t length = strlen(dir) + MAX_PATH_LEN; char *path = MALLOC(length); for (unsigned i = 0; i < npools; ++i) { int ret = snprintf(path, length, "%s"OS_DIR_SEP_STR"testfile%d", dir, i); if (ret < 0 || ret >= length) UT_FATAL("!snprintf"); pops[i] = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR); if (pops[i] == NULL) UT_FATAL("!pmemobj_create"); } PMEMoid *oids = MALLOC(npools * sizeof(PMEMoid)); UT_ASSERTne(oids, NULL); PMEMoid *tmpoids = MALLOC(npools * sizeof(PMEMoid)); UT_ASSERTne(tmpoids, NULL); oids[0] = OID_NULL; UT_ASSERTeq(obj_direct(oids[0]), NULL); for (unsigned i = 0; i < npools; ++i) { oids[i] = (PMEMoid) {pops[i]->uuid_lo, 0}; UT_ASSERTeq(obj_direct(oids[i]), NULL); uint64_t off = pops[i]->heap_offset; oids[i] = (PMEMoid) {pops[i]->uuid_lo, off}; UT_ASSERTeq((char *)obj_direct(oids[i]) - off, (char *)pops[i]); r = pmemobj_alloc(pops[i], &tmpoids[i], 100, 1, NULL, NULL); UT_ASSERTeq(r, 0); } r = pmemobj_alloc(pops[0], &thread_oid, 100, 2, NULL, NULL); UT_ASSERTeq(r, 0); UT_ASSERTne(obj_direct(thread_oid), NULL); os_thread_t t; PTHREAD_CREATE(&t, NULL, test_worker, NULL); /* wait for the worker thread to perform the first check */ os_mutex_lock(&lock1); while (!cond1) os_cond_wait(&sync_cond1, &lock1); os_mutex_unlock(&lock1); for (unsigned i = 0; i < npools; ++i) { UT_ASSERTne(obj_direct(tmpoids[i]), NULL); pmemobj_free(&tmpoids[i]); UT_ASSERTeq(obj_direct(tmpoids[i]), NULL); pmemobj_close(pops[i]); UT_ASSERTeq(obj_direct(oids[i]), NULL); } /* signal the worker that we're free and closed */ os_mutex_lock(&lock2); cond2 = 1; os_cond_signal(&sync_cond2); os_mutex_unlock(&lock2); PTHREAD_JOIN(&t, NULL); os_cond_destroy(&sync_cond1); os_cond_destroy(&sync_cond2); os_mutex_destroy(&lock1); os_mutex_destroy(&lock2); FREE(pops); FREE(tmpoids); FREE(oids); DONE(NULL); }