src/os/linux/vm/os_linux.cpp
Print this page
rev 3492 : imported patch linux_thread_name.patch
rev 3493 : imported patch psgc-bind-procs.patch
@@ -4354,18 +4354,112 @@
snprintf(buf, sizeof(buf), "%s", name);
pthread_setname_np(pthread_self(), buf);
}
}
+// TODO: This is almost 100% copied from os_solaris.cpp,
+// it can and should be extracted into a shared method.
+static bool assign_distribution(uint* id_array,
+ uint id_length,
+ uint* distribution,
+ uint distribution_length) {
+ // Quick check to see if we won't succeed.
+ if (id_length < distribution_length) {
+ return false;
+ }
+ // Assign processor ids to the distribution.
+ // Try to shuffle processors to distribute work across boards,
+ // assuming 4 processors per board.
+ const uint processors_per_board = ProcessDistributionStride;
+ // Find the maximum processor id.
+ uint max_id = 0;
+ for (uint m = 0; m < id_length; m += 1) {
+ max_id = MAX2(max_id, id_array[m]);
+ }
+ // The next id, to limit loops.
+ const uint limit_id = max_id + 1;
+ // Make up markers for available processors.
+ bool* available_id = NEW_C_HEAP_ARRAY(bool, limit_id, mtInternal);
+ for (uint c = 0; c < limit_id; c += 1) {
+ available_id[c] = false;
+ }
+ for (uint a = 0; a < id_length; a += 1) {
+ available_id[id_array[a]] = true;
+ }
+ // Step by "boards", then by "slot", copying to "assigned".
+ // NEEDS_CLEANUP: The assignment of processors should be stateful,
+ // remembering which processors have been assigned by
+ // previous calls, etc., so as to distribute several
+ // independent calls of this method. What we'd like is
+ // It would be nice to have an API that let us ask
+ // how many processes are bound to a processor,
+ // but we don't have that, either.
+ // In the short term, "board" is static so that
+ // subsequent distributions don't all start at board 0.
+ static uint board = 0;
+ uint assigned = 0;
+ // Until we've found enough processors ....
+ while (assigned < distribution_length) {
+ // ... find the next available processor in the board.
+ for (uint slot = 0; slot < processors_per_board; slot += 1) {
+ uint try_id = board * processors_per_board + slot;
+ if ((try_id < limit_id) && (available_id[try_id] == true)) {
+ distribution[assigned] = try_id;
+ available_id[try_id] = false;
+ assigned += 1;
+ break;
+ }
+ }
+ board += 1;
+ if (board * processors_per_board + 0 >= limit_id) {
+ board = 0;
+ }
+ }
+ if (available_id != NULL) {
+ FREE_C_HEAP_ARRAY(bool, available_id, mtInternal);
+ }
+ return true;
+}
+
bool os::distribute_processes(uint length, uint* distribution) {
- // Not yet implemented.
+
+ cpu_set_t cpu_set;
+
+ int result = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu_set);
+
+ if (result == 0) {
+
+ uint cpu_ids_length;
+ uint *cpu_ids;
+ uint cpu_ids_found = 0;
+
+ cpu_ids_length = CPU_COUNT(&cpu_set);
+
+ cpu_ids = NEW_C_HEAP_ARRAY(uint, cpu_ids_length, mtInternal);
+
+ for (uint i = 0; i < CPU_SETSIZE && cpu_ids_found < cpu_ids_length; i++) {
+ if (CPU_ISSET(i, &cpu_set)) {
+ cpu_ids[cpu_ids_found] = i;
+ cpu_ids_found++;
+ }
+ }
+ bool result = assign_distribution(cpu_ids, cpu_ids_length, distribution, length);
+
+ FREE_C_HEAP_ARRAY(uint, cpu_ids, mtInternal);
+
+ return result;
+ }
return false;
}
bool os::bind_to_processor(uint processor_id) {
- // Not yet implemented.
- return false;
+ cpu_set_t cpu_set;
+ CPU_ZERO(&cpu_set);
+ CPU_SET(processor_id, &cpu_set);
+ pthread_t current_thread = pthread_self();
+ int result = pthread_setaffinity_np(current_thread, sizeof(cpu_set), &cpu_set);
+ return result;
}
///
// Suspends the target using the signal mechanism and then grabs the PC before