int list_ins_next(sllist_t *lst, sllistItm_t *itm, const void *data) { //sllistItm_t *plitm = (sllistItm_t *) malloc(sizeof(sllistItm_t)); sllistItm_t *plitm = xmalloc0(sizeof(sllistItm_t)); // test that allocation was successful, if not return -1 if (plitm == NULL) return -1; // OK now, cast to avoid warning: assigning to 'void *' from 'const void *' discards qualifiers plitm->data = (void *) data; // insertion - 4 cases if (lst->size == 0) { // (1) empty list, so actually itm is NULL plitm->next = lst->tail; lst->tail = lst->head = plitm; } else if (itm == NULL) { // (2) list_size >0 => list is not empty, but itm == NULL // => insertion at the head plitm->next = lst->head; lst->head = plitm; } else { // (3) and (4) plitm->next = itm->next; itm->next = plitm; if (plitm->next == NULL) lst->tail = plitm; } // insertion OK, increase the size list by 1 lst->size++; return 0; }
struct img_ctx *img_ctx_new(int w, int h, img_type_t type, color_type_t color) { struct img_ctx *c; int len; c = xmalloc(sizeof(*c)); c->type = type; c->w = w; c->h = h; len = w*h; switch (type) { case TYPE_GRAY: c->pix = xmalloc0(len*sizeof(*(c->pix))); /* initialize pixels to spcified color */ if (color != C_NONE) memset(c->pix, color, len*sizeof(*(c->pix))); break; case TYPE_RGB: c->r = xmalloc(len*sizeof(*(c->r))); c->g = xmalloc(len*sizeof(*(c->g))); c->b = xmalloc(len*sizeof(*(c->b))); break; default: abort(); } return c; }
struct gputop_hash_table * gputop_hash_table_create(void *mem_ctx, uint32_t (*key_hash_function)(const void *key), bool (*key_equals_function)(const void *a, const void *b)) { struct gputop_hash_table *ht; ht = xmalloc(sizeof(struct gputop_hash_table)); if (ht == NULL) return NULL; ht->size_index = 0; ht->size = hash_sizes[ht->size_index].size; ht->rehash = hash_sizes[ht->size_index].rehash; ht->max_entries = hash_sizes[ht->size_index].max_entries; ht->key_hash_function = key_hash_function; ht->key_equals_function = key_equals_function; ht->table = xmalloc0(sizeof (struct gputop_hash_entry) * ht->size); ht->entries = 0; ht->deleted_entries = 0; ht->deleted_key = &deleted_key_value; if (ht->table == NULL) { free(ht); return NULL; } return ht; }
bool gputop_perf_oa_trace_open(gputop_perf_query_type_t query_type) { int period_exponent; double duration = 5.0; /* seconds */ uint64_t period_ns; uint64_t n_samples; char *error = NULL; assert(gputop_current_perf_query == NULL); if (!gputop_perf_initialize()) return false; current_user = &trace_user; gputop_current_perf_query = &perf_queries[query_type]; /* The timestamp for HSW+ increments every 80ns * * The period_exponent gives a sampling period as follows: * sample_period = 80ns * 2^(period_exponent + 1) * * Sample ~ every 1 millisecond... */ period_exponent = 11; gputop_current_perf_stream = gputop_perf_open_i915_oa_query(gputop_current_perf_query, period_exponent, 32 * page_size, perf_ready_cb, false, &error); if (!gputop_current_perf_stream) { gputop_log(GPUTOP_LOG_LEVEL_HIGH, error, -1); free(error); gputop_current_perf_query = NULL; return false; } period_ns = 80 * (2 << period_exponent); n_samples = (duration * 1000000000.0) / period_ns; n_samples *= 1.25; /* a bit of leeway */ gputop_perf_trace_buffer_size = n_samples * gputop_current_perf_query->perf_raw_size; gputop_perf_trace_buffer = xmalloc0(gputop_perf_trace_buffer_size); gputop_perf_trace_head = gputop_perf_trace_buffer; gputop_perf_trace_empty = true; gputop_perf_trace_full = false; return true; }
static torrent_array *torrent_array_new(size_t size) { torrent_array *array = xmalloc(sizeof(torrent_array)); array->torrents = xmalloc(sizeof(torrent_info*)*size); for (size_t i = 0; i < size; ++i) { array->torrents[i] = xmalloc0(sizeof(torrent_info)); } array->size = size; return array; }
int list_new(sllist_t **lst, int (*match)(const void *k1, const void *k2), void (*destroy)(void *data), void (*cb)(const void *data)) { /* *lst = (sllist_t *) malloc(sizeof(sllist_t)); if (*lst == NULL) return -1; // fail to allocate space for the new list */ *lst = xmalloc0(sizeof(sllist_t)); list_init(*lst, match, destroy, cb); return 0; }
static void adjust_list_capacity() { if(list_capacity < 1) list_capacity = INITIAL_LIST_CAPACITY; else if(items >= list_capacity) list_capacity *= 2; else if(list_capacity / 2 > items) list_capacity /= 2; else return; if(database) database = xrealloc(database,sizeof(list_item) * list_capacity); else /* allocate memory _and_ initialize pointers to NULL */ database = xmalloc0(sizeof(list_item) * list_capacity); selected = xrealloc(selected, list_capacity); }
/* * Initiate background process for receiving xlog during the backup. * The background stream will use its own database connection so we can * stream the logfile in parallel with the backups. */ static void StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier) { logstreamer_param *param; param = xmalloc0(sizeof(logstreamer_param)); param->timeline = timeline; param->sysidentifier = sysidentifier; /* Convert the starting position */ if (sscanf(startpos, "%X/%X", ¶m->startptr.xlogid, ¶m->startptr.xrecoff) != 2) { fprintf(stderr, _("%s: invalid format of xlog location: %s\n"), progname, startpos); disconnect_and_exit(1); } /* Round off to even segment position */ param->startptr.xrecoff -= param->startptr.xrecoff % XLOG_SEG_SIZE; #ifndef WIN32 /* Create our background pipe */ if (pgpipe(bgpipe) < 0) { fprintf(stderr, _("%s: could not create pipe for background process: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } #endif /* Get a second connection */ param->bgconn = GetConnection(); /* * Always in plain format, so we can write to basedir/pg_xlog. But the * directory entry in the tar file may arrive later, so make sure it's * created before we start. */ snprintf(param->xlogdir, sizeof(param->xlogdir), "%s/pg_xlog", basedir); verify_dir_is_empty_or_create(param->xlogdir); /* * Start a child process and tell it to start streaming. On Unix, this is * a fork(). On Windows, we create a thread. */ #ifndef WIN32 bgchild = fork(); if (bgchild == 0) { /* in child process */ exit(LogStreamerMain(param)); } else if (bgchild < 0) { fprintf(stderr, _("%s: could not create background process: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } /* * Else we are in the parent process and all is well. */ #else /* WIN32 */ bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL); if (bgchild == 0) { fprintf(stderr, _("%s: could not create background thread: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } #endif }
/* * Open a new WAL file in the specified directory. Store the name * (not including the full directory) in namebuf. Assumes there is * enough room in this buffer... * * The file will be padded to 16Mb with zeroes. */ static int open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir, char *namebuf) { int f; char fn[MAXPGPATH]; struct stat statbuf; char *zerobuf; int bytes; XLogFileName(namebuf, timeline, startpoint.xlogid, startpoint.xrecoff / XLOG_SEG_SIZE); snprintf(fn, sizeof(fn), "%s/%s.partial", basedir, namebuf); f = open(fn, O_WRONLY | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR); if (f == -1) { fprintf(stderr, _("%s: could not open transaction log file \"%s\": %s\n"), progname, fn, strerror(errno)); return -1; } /* * Verify that the file is either empty (just created), or a complete * XLogSegSize segment. Anything in between indicates a corrupt file. */ if (fstat(f, &statbuf) != 0) { fprintf(stderr, _("%s: could not stat transaction log file \"%s\": %s\n"), progname, fn, strerror(errno)); close(f); return -1; } if (statbuf.st_size == XLogSegSize) return f; /* File is open and ready to use */ if (statbuf.st_size != 0) { fprintf(stderr, _("%s: transaction log file \"%s\" has %d bytes, should be 0 or %d\n"), progname, fn, (int) statbuf.st_size, XLogSegSize); close(f); return -1; } /* New, empty, file. So pad it to 16Mb with zeroes */ zerobuf = xmalloc0(XLOG_BLCKSZ); for (bytes = 0; bytes < XLogSegSize; bytes += XLOG_BLCKSZ) { if (write(f, zerobuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) { fprintf(stderr, _("%s: could not pad transaction log file \"%s\": %s\n"), progname, fn, strerror(errno)); free(zerobuf); close(f); unlink(fn); return -1; } } free(zerobuf); if (lseek(f, SEEK_SET, 0) != 0) { fprintf(stderr, _("%s: could not seek to beginning of transaction log file \"%s\": %s\n"), progname, fn, strerror(errno)); close(f); return -1; } return f; }
/* * Connect to the server. Returns a valid PGconn pointer if connected, * or NULL on non-permanent error. On permanent error, the function will * call exit(1) directly. */ PGconn * GetConnection(void) { PGconn *tmpconn; int argcount = 4; /* dbname, replication, fallback_app_name, * password */ int i; const char **keywords; const char **values; char *password = NULL; const char *tmpparam; if (dbhost) argcount++; if (dbuser) argcount++; if (dbport) argcount++; keywords = xmalloc0((argcount + 1) * sizeof(*keywords)); values = xmalloc0((argcount + 1) * sizeof(*values)); keywords[0] = "dbname"; values[0] = "replication"; keywords[1] = "replication"; values[1] = "true"; keywords[2] = "fallback_application_name"; values[2] = progname; i = 3; if (dbhost) { keywords[i] = "host"; values[i] = dbhost; i++; } if (dbuser) { keywords[i] = "user"; values[i] = dbuser; i++; } if (dbport) { keywords[i] = "port"; values[i] = dbport; i++; } while (true) { if (password) free(password); if (dbpassword) { /* * We've saved a password when a previous connection succeeded, * meaning this is the call for a second session to the same * database, so just forcibly reuse that password. */ keywords[argcount - 1] = "password"; values[argcount - 1] = dbpassword; dbgetpassword = -1; /* Don't try again if this fails */ } else if (dbgetpassword == 1) { password = simple_prompt(_("Password: "******"password"; values[argcount - 1] = password; } tmpconn = PQconnectdbParams(keywords, values, true); /* * If there is too little memory even to allocate the PGconn object * and PQconnectdbParams returns NULL, we call exit(1) directly. */ if (!tmpconn) { fprintf(stderr, _("%s: could not connect to server\n"), progname); exit(1); } if (PQstatus(tmpconn) == CONNECTION_BAD && PQconnectionNeedsPassword(tmpconn) && dbgetpassword != -1) { dbgetpassword = 1; /* ask for password next time */ PQfinish(tmpconn); continue; } if (PQstatus(tmpconn) != CONNECTION_OK) { fprintf(stderr, _("%s: could not connect to server: %s\n"), progname, PQerrorMessage(tmpconn)); PQfinish(tmpconn); free(values); free(keywords); return NULL; } /* Connection ok! */ free(values); free(keywords); /* * Ensure we have the same value of integer timestamps as the server * we are connecting to. */ tmpparam = PQparameterStatus(tmpconn, "integer_datetimes"); if (!tmpparam) { fprintf(stderr, _("%s: could not determine server setting for integer_datetimes\n"), progname); PQfinish(tmpconn); exit(1); } #ifdef HAVE_INT64_TIMESTAMP if (strcmp(tmpparam, "on") != 0) #else if (strcmp(tmpparam, "off") != 0) #endif { fprintf(stderr, _("%s: integer_datetimes compile flag does not match server\n"), progname); PQfinish(tmpconn); exit(1); } /* Store the password for next run */ if (password) dbpassword = password; return tmpconn; } }
struct gputop_perf_stream * gputop_perf_open_generic_counter(int pid, int cpu, uint64_t type, uint64_t config, size_t perf_buffer_size, void (*ready_cb)(uv_poll_t *poll, int status, int events), bool overwrite, char **error) { struct gputop_perf_stream *stream; struct perf_event_attr attr; int event_fd; uint8_t *mmap_base; int expected_max_samples; size_t sample_size = 0; memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.type = type; attr.config = config; attr.sample_type = PERF_SAMPLE_READ | PERF_SAMPLE_TIME; attr.sample_period = 1; attr.watermark = true; attr.wakeup_watermark = perf_buffer_size / 4; event_fd = perf_event_open(&attr, pid, cpu, -1, /* group fd */ PERF_FLAG_FD_CLOEXEC); /* flags */ if (event_fd == -1) { asprintf(error, "Error opening i915_oa perf event: %m\n"); return NULL; } /* NB: A read-write mapping ensures the kernel will stop writing data when * the buffer is full, and will report samples as lost. */ mmap_base = mmap(NULL, perf_buffer_size + page_size, PROT_READ | PROT_WRITE, MAP_SHARED, event_fd, 0); if (mmap_base == MAP_FAILED) { asprintf(error, "Error mapping circular buffer, %m\n"); close (event_fd); return NULL; } stream = xmalloc0(sizeof(*stream)); stream->type = GPUTOP_STREAM_PERF; stream->ref_count = 1; stream->fd = event_fd; stream->perf.buffer = mmap_base + page_size; stream->perf.buffer_size = perf_buffer_size; stream->perf.mmap_page = (void *)mmap_base; sample_size = sizeof(struct perf_event_header) + 8; /* _TIME */ expected_max_samples = (stream->perf.buffer_size / sample_size) * 1.2; memset(&stream->perf.header_buf, 0, sizeof(stream->perf.header_buf)); stream->overwrite = overwrite; if (overwrite) { stream->perf.header_buf.len = expected_max_samples; stream->perf.header_buf.offsets = xmalloc(sizeof(uint32_t) * expected_max_samples); } stream->fd_poll.data = stream; uv_poll_init(gputop_ui_loop, &stream->fd_poll, stream->fd); uv_poll_start(&stream->fd_poll, UV_READABLE, ready_cb); return stream; }
struct gputop_perf_stream * gputop_perf_open_trace(int pid, int cpu, const char *system, const char *event, size_t trace_struct_size, size_t perf_buffer_size, void (*ready_cb)(uv_poll_t *poll, int status, int events), bool overwrite, char **error) { struct gputop_perf_stream *stream; struct perf_event_attr attr; int event_fd; uint8_t *mmap_base; int expected_max_samples; char *filename = NULL; int id = 0; size_t sample_size = 0; asprintf(&filename, "/sys/kernel/debug/tracing/events/%s/%s/id", system, event); if (filename) { struct stat st; if (stat(filename, &st) < 0) { int err = errno; free(filename); filename = NULL; if (err == EPERM) { asprintf(error, "Permission denied to open tracepoint %s:%s" " (Linux tracepoints require root privileges)", system, event); return NULL; } else { asprintf(error, "Failed to open tracepoint %s:%s: %s", system, event, strerror(err)); return NULL; } } } id = read_file_uint64(filename); free(filename); filename = NULL; memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.type = PERF_TYPE_TRACEPOINT; attr.config = id; attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_TIME; attr.sample_period = 1; attr.watermark = true; attr.wakeup_watermark = perf_buffer_size / 4; event_fd = perf_event_open(&attr, pid, cpu, -1, /* group fd */ PERF_FLAG_FD_CLOEXEC); /* flags */ if (event_fd == -1) { asprintf(error, "Error opening i915_oa perf event: %m\n"); return NULL; } /* NB: A read-write mapping ensures the kernel will stop writing data when * the buffer is full, and will report samples as lost. */ mmap_base = mmap(NULL, perf_buffer_size + page_size, PROT_READ | PROT_WRITE, MAP_SHARED, event_fd, 0); if (mmap_base == MAP_FAILED) { asprintf(error, "Error mapping circular buffer, %m\n"); close (event_fd); return NULL; } stream = xmalloc0(sizeof(*stream)); stream->type = GPUTOP_STREAM_PERF; stream->ref_count = 1; stream->fd = event_fd; stream->perf.buffer = mmap_base + page_size; stream->perf.buffer_size = perf_buffer_size; stream->perf.mmap_page = (void *)mmap_base; sample_size = sizeof(struct perf_event_header) + 8 /* _TIME */ + trace_struct_size; /* _RAW */ expected_max_samples = (stream->perf.buffer_size / sample_size) * 1.2; memset(&stream->perf.header_buf, 0, sizeof(stream->perf.header_buf)); stream->overwrite = overwrite; if (overwrite) { stream->perf.header_buf.len = expected_max_samples; stream->perf.header_buf.offsets = xmalloc(sizeof(uint32_t) * expected_max_samples); } stream->fd_poll.data = stream; uv_poll_init(gputop_ui_loop, &stream->fd_poll, stream->fd); uv_poll_start(&stream->fd_poll, UV_READABLE, ready_cb); return stream; }
struct gputop_perf_stream * gputop_open_i915_perf_oa_query(struct gputop_perf_query *query, int period_exponent, size_t perf_buffer_size, void (*ready_cb)(uv_poll_t *poll, int status, int events), bool overwrite, char **error) { struct gputop_perf_stream *stream; struct i915_perf_open_param param; struct i915_perf_oa_attr oa_attr; int ret; memset(¶m, 0, sizeof(param)); memset(&oa_attr, 0, sizeof(oa_attr)); param.type = I915_PERF_OA_EVENT; param.flags = 0; param.flags |= I915_PERF_FLAG_FD_CLOEXEC; param.flags |= I915_PERF_FLAG_FD_NONBLOCK; param.sample_flags = I915_PERF_SAMPLE_OA_REPORT; oa_attr.size = sizeof(oa_attr); oa_attr.flags |= I915_OA_FLAG_PERIODIC; oa_attr.oa_format = query->perf_oa_format; oa_attr.metrics_set = query->perf_oa_metrics_set; oa_attr.oa_timer_exponent = period_exponent; param.attr = (uintptr_t)&oa_attr; ret = perf_ioctl(drm_fd, I915_IOCTL_PERF_OPEN, ¶m); if (ret == -1) { asprintf(error, "Error opening i915_oa perf event: %m\n"); return NULL; } stream = xmalloc0(sizeof(*stream)); stream->type = GPUTOP_STREAM_I915_PERF; stream->ref_count = 1; stream->query = query; stream->fd = param.fd; /* We double buffer the samples we read from the kernel so * we can maintain a stream->last pointer for calculating * counter deltas */ stream->oa.buf_sizes = MAX_I915_PERF_OA_SAMPLE_SIZE * 100; stream->oa.bufs[0] = xmalloc0(stream->oa.buf_sizes); stream->oa.bufs[1] = xmalloc0(stream->oa.buf_sizes); stream->overwrite = overwrite; if (overwrite) { #warning "TODO: support flight-recorder mode" assert(0); } stream->fd_poll.data = stream; uv_poll_init(gputop_ui_loop, &stream->fd_poll, stream->fd); uv_poll_start(&stream->fd_poll, UV_READABLE, ready_cb); return stream; }
struct gputop_perf_stream * gputop_perf_open_i915_oa_query(struct gputop_perf_query *query, int period_exponent, size_t perf_buffer_size, void (*ready_cb)(uv_poll_t *poll, int status, int events), bool overwrite, char **error) { struct gputop_perf_stream *stream; i915_oa_attr_t oa_attr; struct perf_event_attr attr; int event_fd; uint8_t *mmap_base; int expected_max_samples; memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.type = lookup_i915_oa_id(); attr.sample_type = PERF_SAMPLE_RAW; attr.sample_period = 1; attr.watermark = true; attr.wakeup_watermark = perf_buffer_size / 4; memset(&oa_attr, 0, sizeof(oa_attr)); oa_attr.size = sizeof(oa_attr); oa_attr.format = query->perf_oa_format; oa_attr.metrics_set = query->perf_oa_metrics_set; oa_attr.timer_exponent = period_exponent; attr.config = (uint64_t)&oa_attr; event_fd = perf_event_open(&attr, -1, /* pid */ 0, /* cpu */ -1, /* group fd */ PERF_FLAG_FD_CLOEXEC); /* flags */ if (event_fd == -1) { asprintf(error, "Error opening i915_oa perf event: %m\n"); return NULL; } /* NB: A read-write mapping ensures the kernel will stop writing data when * the buffer is full, and will report samples as lost. */ mmap_base = mmap(NULL, perf_buffer_size + page_size, PROT_READ | PROT_WRITE, MAP_SHARED, event_fd, 0); if (mmap_base == MAP_FAILED) { asprintf(error, "Error mapping circular buffer, %m\n"); close (event_fd); return NULL; } stream = xmalloc0(sizeof(*stream)); stream->type = GPUTOP_STREAM_PERF; stream->ref_count = 1; stream->query = query; stream->fd = event_fd; stream->perf.buffer = mmap_base + page_size; stream->perf.buffer_size = perf_buffer_size; stream->perf.mmap_page = (void *)mmap_base; expected_max_samples = (stream->perf.buffer_size / MAX_CORE_PERF_OA_SAMPLE_SIZE) * 1.2; memset(&stream->perf.header_buf, 0, sizeof(stream->perf.header_buf)); stream->overwrite = overwrite; if (overwrite) { stream->perf.header_buf.len = expected_max_samples; stream->perf.header_buf.offsets = xmalloc(sizeof(uint32_t) * expected_max_samples); } stream->fd_poll.data = stream; uv_poll_init(gputop_ui_loop, &stream->fd_poll, stream->fd); uv_poll_start(&stream->fd_poll, UV_READABLE, ready_cb); return stream; }
list_item item_create() { return xmalloc0(ITEM_SIZE); }