static bool get_free_sockets(const char* topology, const int topology_length, int** sockets, int* sockets_size) { /* temporary counter */ int i, j; /* this number of sockets we discovered already */ int socket_number = 0; (*sockets) = NULL; (*sockets_size) = 0; /* go through the whole topology and check if there are some sockets completely unbound */ for (i = 0; i < topology_length && topology[i] != '\0'; i++) { if (topology[i] == 'S' || topology[i] == 's') { /* we're on a new socket: check all cores (and skip threads) after it */ bool free = true; /* check the topology till the next socket (or end) */ for (j = i + 1; j < topology_length && topology[j] != '\0'; j++) { if (topology[j] == 'c') { /* this socket has at least one core in use */ free = false; } else if (topology[j] == 'S' || topology[j] == 's') { break; } } /* fast forward */ i = j; /* check if this socket had a core in use */ if (free == true) { /* this socket can be used completely */ (*sockets) = sge_realloc(*sockets, ((*sockets_size)+1)*sizeof(int), 1); (*sockets)[(*sockets_size)] = socket_number; (*sockets_size)++; } /* increment the number of sockets we discovered so far */ socket_number++; } /* end if this is a socket */ } /* it was successful when we found at least one socket not used by any job */ if ((*sockets_size) > 0) { /* we also have to free the list outside afterwards */ return true; } else { return false; } }
static void sge_dstring_allocate(dstring *sb, size_t request) { /* always request multiples of REALLOC_CHUNK */ size_t chunks = request / REALLOC_CHUNK + 1; request = chunks * REALLOC_CHUNK; /* set new size */ sb->size += request; /* allocate memory */ if (sb->s != NULL) { sb->s = sge_realloc(sb->s, sb->size * sizeof(char), 1); } else { sb->s = malloc(sb->size * sizeof(char)); sb->s[0] = '\0'; } }
/****** uti/io/sge_stream2string() ******************************************** * NAME * sge_stream2string() -- Read string from stream * * SYNOPSIS * char* sge_stream2string(FILE *fp, int *len) * * FUNCTION * Read string from stream * * INPUTS * FILE *fp - file descriptor * int *len - number of bytes read * * RESULT * char* - pointer to malloced string buffer * * SEE ALSO * uti/io/sge_file2string() * uti/io/sge_string2file() * * NOTES * MT-NOTE: sge_stream2string() is MT safe ******************************************************************************/ char *sge_stream2string(FILE *fp, int *len) { char *str; int filled = 0; int malloced_len, i; DENTER(TOP_LAYER, "sge_stream2string"); if (!(str = malloc(FILE_CHUNK))) { DEXIT; return NULL; } malloced_len = FILE_CHUNK; /* malloced_len-filled-1 cause we reserve space for \0 termination */ while ((i = fread(&str[filled], 1, malloced_len-filled-1, fp)) > 0) { filled += i; if (malloced_len == filled+1) { str = sge_realloc(str, malloced_len + FILE_CHUNK, 0); if (str == NULL) { DEXIT; return NULL; } malloced_len += FILE_CHUNK; } if (feof(fp)) { DPRINTF(("got EOF\n")); break; } } str[filled] = '\0'; /* NULL termination */ *len = filled; DEXIT; return str; }
int kupdate(int avenrun[3]) { kstat_t *ks; kid_t nkcid; int i; int changed = 0; static int ncpu = 0; static kid_t kcid = 0; kstat_named_t *kn; /* * 0. kstat_open */ if (!kc) { kc = kstat_open(); if (!kc) { perror("kstat_open "); return -1; } changed = 1; kcid = kc->kc_chain_id; } /* keep doing it until no more changes */ kcid_changed: /* * 1. kstat_chain_update */ nkcid = kstat_chain_update(kc); if (nkcid) { /* UPDKCID will abort if nkcid is -1, so no need to check */ changed = 1; kcid = nkcid; } UPDKCID(nkcid,0); ks = kstat_lookup(kc, "unix", 0, "system_misc"); if (kstat_read(kc, ks, 0) == -1) { perror("kstat_read"); return -1; } #if 0 /* load average */ kn = kstat_data_lookup(ks, "avenrun_1min"); if (kn) avenrun[0] = kn->value.ui32; kn = kstat_data_lookup(ks, "avenrun_5min"); if (kn) avenrun[1] = kn->value.ui32; kn = kstat_data_lookup(ks, "avenrun_15min"); if (kn) avenrun[2] = kn->value.ui32; /* nproc */ kn = kstat_data_lookup(ks, "nproc"); if (kn) { nproc = kn->value.ui32; #ifdef NO_NPROC if (nproc > maxprocs) reallocproc(2 * nproc); #endif } #endif if (changed) { int ncpus = 0; /* * 2. get data addresses */ ncpu = 0; kn = kstat_data_lookup(ks, "ncpus"); if (kn && kn->value.ui32 > ncpus) { ncpus = kn->value.ui32; cpu_ks = (kstat_t **)sge_realloc(cpu_ks, ncpus * sizeof(kstat_t *), 1); cpu_stat = (cpu_stat_t *)sge_realloc(cpu_stat, ncpus * sizeof(cpu_stat_t), 1); } for (ks = kc->kc_chain; ks; ks = ks->ks_next) { if (strncmp(ks->ks_name, "cpu_stat", 8) == 0) { nkcid = kstat_read(kc, ks, NULL); /* if kcid changed, pointer might be invalid */ UPDKCID(nkcid, kcid); cpu_ks[ncpu] = ks; ncpu++; if (ncpu >= ncpus) { break; } } } /* note that ncpu could be less than ncpus, but that's okay */ changed = 0; } /* * 3. get data */ for (i = 0; i < ncpu; i++) { nkcid = kstat_read(kc, cpu_ks[i], &cpu_stat[i]); /* if kcid changed, pointer might be invalid */ UPDKCID(nkcid, kcid); } /* return the number of cpus found */ return(ncpu); }
static const char* sge_dstring_vsprintf_copy_append(dstring *sb, sge_dstring_copy_append_f function, const char *format, va_list ap) { const char *ret = NULL; if (sb != NULL && format != NULL && function != NULL) { char static_buffer[BUFSIZ]; int vsnprintf_ret; va_list ap_copy; va_copy(ap_copy, ap); vsnprintf_ret = vsnprintf(static_buffer, BUFSIZ, format, ap_copy); va_end(ap_copy); /* * We have to handle three cases here: * 1) If the function returns -1 then vsprintf does not follow * the C99 standard. We have to increase the buffer until * all parameters fit into the buffer. * 2) The function returns a value >BUFSIZE. This indicates * that the function follows the C99 standard. * vsnprintf_ret is the number of characters which would * have been written to the buffer if it where large enough. * We have to create a buffer of this size. * 3) If the return value is >0 and <BUFSIZ than vsprintf * was successfull. We do not need a dyn_buffer. */ if (vsnprintf_ret == -1) { size_t dyn_size = 2 * BUFSIZ; char *dyn_buffer = sge_malloc(dyn_size); while (vsnprintf_ret == -1 && dyn_buffer != NULL) { va_copy(ap_copy, ap); vsnprintf_ret = vsnprintf(dyn_buffer, dyn_size, format, ap_copy); va_end(ap_copy); if (vsnprintf_ret == -1) { dyn_size *= 2; dyn_buffer = sge_realloc(dyn_buffer, dyn_size, 0); } } if (dyn_buffer != NULL) { ret = function(sb, dyn_buffer); sge_free(&dyn_buffer); } else { /* error: no memory */ ret = NULL; } } else if (vsnprintf_ret > BUFSIZ) { char *dyn_buffer = NULL; dyn_buffer = (char *)malloc((vsnprintf_ret + 1) * sizeof(char)); if (dyn_buffer != NULL) { va_copy(ap_copy, ap); vsnprintf(dyn_buffer, vsnprintf_ret + 1, format, ap_copy); va_end(ap_copy); ret = function(sb, dyn_buffer); sge_free(&dyn_buffer); } else { /* error: no memory */ ret = NULL; } } else { ret = function(sb, static_buffer); } } return ret; }
/****** uti/io/sge_bin2string() *********************************************** * NAME * sge_bin2string() -- Put binary stream into a string * * SYNOPSIS * char* sge_bin2string(FILE *fp, int size) * * FUNCTION * Read a binary steam from given file descriptor 'fp' and * write it into (dynamically) malloced buffer as "ASCII" format. * * "ASCII" format means: * '\0' is written as '\\' '\0' * '\\' is written as '\\' '\\' * End of buffer is written as '\0' * * INPUTS * FILE *fp - file descriptor * int size - size of the buffer used within this function * * RESULT * char* - malloced buffer * * SEE ALSO * uti/io/sge_string2bin() * * NOTES * MT-NOTE: sge_bin2string() is MT safe ******************************************************************************/ char *sge_bin2string(FILE *fp, int size) { int i, fd; char inbuf[BUFFER], outbuf[2*BUFFER]; char *inp, *outp; char *dstbuf; int len, /* length of current tmp buffer */ dstbuflen, /* total length of destination buffer */ chunksize, /* chunks for realloc */ lastpos, /* last position in destination buffer */ error; if ((fd = fileno(fp)) == -1) return NULL; chunksize = 20480; if (size <= 0) /* no idea about buffer, malloc in chunks */ size = chunksize; dstbuf = (char *) malloc(size+1); dstbuflen = size; lastpos = 0; error = false; while (!error) { i = read(fd, inbuf, BUFFER); if (i > 0) { inp = inbuf; outp = outbuf; while (inp < &inbuf[i]) { if (*inp == '\\') { *outp++ = '\\'; *outp++ = '\\'; } else if (*inp == '\0') { *outp++ = '\\'; *outp++ = '0'; } else *outp++ = *inp; inp++; } len = outp - outbuf; if (lastpos + len > dstbuflen) { if ((dstbuf = sge_realloc(dstbuf, lastpos + len + chunksize, 0)) == NULL) { error = true; break; } dstbuflen = lastpos + len + chunksize; } memcpy(&dstbuf[lastpos], outbuf, len); lastpos += len; } else if (i == 0) { break; } else { if (errno != EINTR) { error=true; break; } } } if (error) { sge_free(&dstbuf); return NULL; } else { if ((dstbuf = sge_realloc(dstbuf, lastpos + 1, 0)) == NULL) { return NULL; } dstbuf[lastpos] = '\0'; return dstbuf; } }
static int account_cores_on_socket(char** topology, const int topology_length, const int socket_number, const int cores_needed, int** list_of_sockets, int* list_of_sockets_size, int** list_of_cores, int* list_of_cores_size) { int i; /* socket number we are at the moment */ int current_socket_number = -1; /* return value */ int retval; /* try to use as many cores as possible on a specific socket but not more */ /* jump to the specific socket given by the "socket_number" */ for (i = 0; i < topology_length && (*topology)[i] != '\0'; i++) { if ((*topology)[i] == 'S' || (*topology)[i] == 's') { current_socket_number++; if (current_socket_number >= socket_number) { /* we are at the beginning of socket #"socket_number" */ break; } } } /* check if we reached that socket or if it was out of range */ if (socket_number != current_socket_number) { /* early abort because we couldn't find the socket we were searching for */ retval = 0; } else { /* we are at a 'S' or 's' and going to the next 'S' or 's' and collecting all cores in between */ int core_counter = 0; /* current core number on the socket */ i++; /* just forward to the first core on the socket */ retval = 0; /* need to initialize the number of cores we found */ for (; i < topology_length && (*topology)[i] != '\0'; i++) { if ((*topology)[i] == 'C') { /* take this core */ (*list_of_sockets_size)++; /* the socket list is growing */ (*list_of_cores_size)++; /* the core list is growing */ *list_of_sockets = sge_realloc(*list_of_sockets, (*list_of_sockets_size) * sizeof(int), 1); *list_of_cores = sge_realloc(*list_of_cores, (*list_of_cores_size) * sizeof(int), 1); /* store the logical <socket,core> tuple inside the lists */ (*list_of_sockets)[(*list_of_sockets_size) - 1] = socket_number; (*list_of_cores)[(*list_of_cores_size) - 1] = core_counter; /* increase the number of cores we've collected so far */ retval++; /* move forward to the next core */ core_counter++; /* do accounting */ (*topology)[i] = 'c'; /* thread binding: accounting is done here */ account_all_threads_after_core(topology, i); } else if ((*topology)[i] == 'c') { /* this core is already in use */ /* move forward to the next core */ core_counter++; } else if ((*topology)[i] == 'S' || (*topology)[i] == 's') { /* we are already on another socket which we can not use */ break; } if (retval >= cores_needed) { /* we have already collected as many cores we need to collect */ break; } } } return retval; }