/** Resizes a block of memory (DEBUG). * * @param[in] file - The file where @e xmemdup was called. * @param[in] line - The line number where @e xmemdup was called. * @param[in] buf - A pointer to a buffer to be resized. * * @return A pointer to the new block on success, or null on failure. * * @remarks This routine emulates the standard library routine, * realloc, including esoteric functionality, such as passing * NULL for @p buf actually allocates a new buffer, passing 0 * for @p size actually allocates a new buffer. */ void * _xrealloc(const char * file, int line, void * ptr, size_t size) { xallocation_t * x; if (!ptr) return _xmalloc(file, line, size); if (!size) { _xfree(file, line, ptr); return 0; } x = _xmalloc_find(ptr); if (x != 0) { void * newptr = ptr; if (x->size != size) { newptr = _xmalloc(file, line, size); memcpy(newptr, ptr, x->size); _xfree(file, line, x); } return newptr; } if (G_xmalloc_fh) fprintf(G_xmalloc_fh, "*** xrealloc called on " "non-xmalloc'd memory ***\n"); return 0; }
/** Duplicates a sized memory buffer (DEBUG). * * @param[in] file - The file where @e xmemdup was called. * @param[in] line - The line number where @e xmemdup was called. * @param[in] ptr - A pointer to the memory block to be duplicated. * @param[in] size - The size of @p ptr in bytes. * * @return A pointer to the duplicated memory block, or NULL on memory * allocation failure. */ void * _xmemdup(const char * file, int line, const void * ptr, size_t size) { void * cpy = _xmalloc(file, line, size); if (cpy) memcpy(cpy, ptr, size); return cpy; }
/** Duplicates a string buffer (DEBUG). * * @param[in] file - The file where @e xmemdup was called. * @param[in] line - The line number where @e xmemdup was called. * @param[in] str - A pointer to the string to be duplicated. * * @return A pointer to the duplicated string, or NULL on memory * allocation failure. */ char * _xstrdup(const char * file, int line, const char * str) { size_t strsz = strlen(str) + 1; char * ptr = _xmalloc(file, line, strsz); if (ptr) memcpy(ptr, str, strsz); return ptr; }
/** Allocates and clears a block of memory (DEBUG). * * Allocates a range of bytes of size @p numblks * @p size, and zeros * the entire memory block. * * @param[in] file - The file where @e xfree was called. * @param[in] line - The line number where @e xfree was called. * @param[in] numblks - The number of blocks of size @p size to allocate. * @param[in] size - The size of each block to allocate. * * @return A pointer to the newly allocated and cleared memory block. */ void * _xcalloc(const char * file, int line, int numblks, size_t size) { size_t blksz = numblks * size; void * ptr = _xmalloc(file, line, blksz); if (ptr) memset(ptr, 0, blksz); return ptr; }
void *lwip_malloc(size_t size) { void *obj = _xmalloc(size, MIN_ALIGN); #ifdef LWIP_DEBUG_MALLOC printk("lwip-malloc: %p, %lu B\n", obj, size); #endif return obj; }
EDGE_C * GRAPH::new_ec(EDGE * e) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (e == NULL) return NULL; EDGE_C * el = m_el_free_list.get_free_elem(); el = (el == NULL) ? (EDGE_C*)_xmalloc(sizeof(EDGE_C)) : el; EC_edge(el) = e; return el; }
char *_xstrdup(const char *s1, const char *filen, int line) { char *s2; s2 = (char *) _xmalloc(strlen(s1)+1, filen, line); if (s2 != NULL) { strcpy(s2, s1); } return (s2); }
void *lwip_calloc(int num, size_t size) { void *obj = _xmalloc((size) * (num), MIN_ALIGN); #ifdef LWIP_DEBUG_MALLOC printk("lwip-calloc: %p, %d * %lu B (= %lu B)\n", obj, num, size, num * size); #endif if(obj) memset(obj, 0, (num) * (size)); return obj; }
static inline char * patch_list_dump_hex (uint8_t * p, int size) { int i = 0, fixed_up = size * 2 + 1; char *buffer = _xmalloc (fixed_up); for (i = 0; i < size; i++) { snprintf (buffer, fixed_up, "%s%02X", buffer, p[i]); } buffer[fixed_up - 1] = '\0'; return buffer; }
EDGE * GRAPH::new_edge_c(VERTEX * from, VERTEX * to) { EDGE * e = m_e_free_list.get_free_elem(); if (e == NULL) { e = (EDGE*)_xmalloc(sizeof(EDGE)); } EDGE_from(e) = from; EDGE_to(e) = to; add_in_list(to, e); add_out_list(from, e); return e; }
/* Allocate a page-aligned bigarray of length [n_pages] pages. Since CAML_BA_MANAGED is set the bigarray C finaliser will call free() whenever all sub-bigarrays are unreachable. */ CAMLprim value caml_alloc_pages(value did_gc, value n_pages) { CAMLparam2(did_gc, n_pages); size_t len = Int_val(n_pages) * PAGE_SIZE; /* If the allocation fails, return None. The ocaml layer will be able to trigger a full GC which just might run finalizers of unused bigarrays which will free some memory. */ #ifdef __MINIOS__ void* block = _xmalloc(len, PAGE_SIZE); if (block == NULL) { #elif _WIN32 /* NB we can't use _aligned_malloc because we can't get OCaml to finalize with _aligned_free. Regular free() will not work. */ static int printed_warning = 0; if (!printed_warning) { printed_warning = 1; printk("WARNING: Io_page on Windows doesn't guarantee alignment\n"); } void *block = malloc(len); if (block == NULL) { #else void* block = NULL; int ret = posix_memalign(&block, PAGE_SIZE, len); if (ret < 0) { #endif if (Bool_val(did_gc)) printk("Io_page: memalign(%d, %zu) failed, even after GC.\n", PAGE_SIZE, len); caml_raise_out_of_memory(); } /* Explicitly zero the page before returning it */ memset(block, 0, len); /* OCaml 4.02 introduced bigarray element type CAML_BA_CHAR, which needs to be used - otherwise type t in io_page.ml is different from the allocated bigarray and equality won't hold. Only since 4.02 there is a <caml/version.h>, thus we cannot include it in order to detect the version of the OCaml runtime. Instead, we use definitions which were introduced by 4.02 - and cross fingers that they'll stay there in the future. Once <4.02 support is removed, we should get rid of this hack. -- hannes, 16th Feb 2015 */ #ifdef Caml_ba_kind_val CAMLreturn(caml_ba_alloc_dims(CAML_BA_CHAR | CAML_BA_C_LAYOUT | CAML_BA_MANAGED, 1, block, len)); #else CAMLreturn(caml_ba_alloc_dims(CAML_BA_UINT8 | CAML_BA_C_LAYOUT | CAML_BA_MANAGED, 1, block, len)); #endif }
void * _block_alloc(unsigned int size, const char *filen, int line) { int i; unsigned int *c; char *p; assert(size > 0); assert(size < MAX_SIZE); i = SIZE_TO_INDEX(size); if (blocks[i] != NULL) { p = (char *)blocks[i]; blocks[i] = blocks[i]->next; xclaim((char*)p - 8, filen, line); } else { #ifdef DEBUG_MEM_BREAK /* This can only go here if this file is merged with memory.c! [oh] */ mem_item[naddr].blen = size; #endif /* DEBUG_MEM_BREAK */ p = (char *) _xmalloc(INDEX_TO_SIZE(i) + 8,filen,line); *((int *)p) = INDEX_TO_SIZE(i); p += 8; blocks_alloced++; } c = (unsigned int *)((char *)p - 8); if (size > *c) { fprintf(stderr, "block_alloc: block is too small %d %d!\n", size, *c); } #ifdef DEBUG_MEM if (blocks_alloced == MAX_BLOCKS_OUT) { debug_msg("Too many blocks allocated.\n"); xmemdist(stderr); xmemdmp(); } blk_out[nblks_out].iov_base = (char*)c; blk_out[nblks_out].iov_len = size; nblks_out++; #endif /* DEBUG_MEM */ c++; *c = size; assert(p != NULL); return (void*)p; }
VERTEX * GRAPH::new_vertex(UINT vid) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); VERTEX * vex = NULL; #ifndef ALWAYS_VERTEX_UNIQUE if (m_is_unique) #endif { VERTEX * v = m_vertexs.find(vid); if (v != NULL) { return v; } } vex = m_v_free_list.get_free_elem(); vex = (vex == NULL) ? (VERTEX*)_xmalloc(sizeof(VERTEX)) : vex; VERTEX_id(vex) = vid; return vex; }
int open(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; int fd; int len; char *freeme = 0; int r; mode_t old_umask = 0, new_umask = 0022; if ((flags & O_CREAT)) { va_start(args, flags); mode = va_arg(args, mode_t); va_end(args); } /* Possibly redirect the filename */ len = strlen(filename); if (*filename == '/' && len > 5 && !strcmp(filename+len-5, ".gcda")) { static const char *prefix; static int prefix_len = -1; if (prefix_len < 0) { prefix = getenv("_GGCOV_GCDA_PREFIX"); prefix_len = (prefix ? strlen(prefix) : 0); if (prefix) fprintf(stderr, "libggcov: look for .gcda files under %s\n", prefix); } if (prefix) { freeme = (char *)_xmalloc(prefix_len + len + 1); strcpy(freeme, prefix); strcat(freeme, filename); filename = freeme; if ((mode & O_ACCMODE) != O_RDONLY) { /* note: ensure other others have read permission * to both the directories and files we create */ r = mkpath(freeme, 0755); if (r < 0) { perror(freeme); return r; } mode |= 0444; old_umask = umask(new_umask); } } } /* Call the real libc open() call */ fd = real_open(filename, flags, mode); #if DEBUG { char flagbuf[256]; fprintf(stderr, "----> open(\"%s\", %s, %o) = %d\n", filename, describe_flags(flags, flagbuf, sizeof(flagbuf)), mode, fd); } #endif if (old_umask != new_umask) umask(old_umask); free(freeme); return fd; }
static struct patch_list * patch_list_object_allocate (void) { return (struct patch_list *) _xmalloc (sizeof (struct patch_list)); }
int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write) { struct blkfront_dev* dev = files[fd].blk.dev; off_t offset = files[fd].blk.offset; struct blkfront_aiocb aiocb; unsigned long long disksize = dev->info.sectors * dev->info.sector_size; unsigned int blocksize = dev->info.sector_size; int blknum; int blkoff; size_t bytes; int rc = 0; int alignedbuf = 0; uint8_t* copybuf = NULL; /* RW 0 bytes is just a NOP */ if(count == 0) { return 0; } /* Check for NULL buffer */ if( buf == NULL ) { errno = EFAULT; return -1; } /* Write mode checks */ if(write) { /*Make sure we have write permission */ if(dev->info.info & VDISK_READONLY || (dev->info.mode != O_RDWR && dev->info.mode != O_WRONLY)) { errno = EACCES; return -1; } /*Make sure disk is big enough for this write */ if(offset + count > disksize) { errno = ENOSPC; return -1; } } /* Read mode checks */ else { /* Reading past the disk? Just return 0 */ if(offset >= disksize) { return 0; } /*If the requested read is bigger than the disk, just * read as much as we can until the end */ if(offset + count > disksize) { count = disksize - offset; } } /* Determine which block to start at and at which offset inside of it */ blknum = offset / blocksize; blkoff = offset % blocksize; /* Optimization: We need to check if buf is aligned to the sector size. * This is somewhat tricky code. We have to add the blocksize - block offset * because the first block may be a partial block and then for every subsequent * block rw the buffer will be offset.*/ if(!((uintptr_t) (buf +(blocksize - blkoff)) & (dev->info.sector_size-1))) { alignedbuf = 1; } /* Setup aiocb block object */ aiocb.aio_dev = dev; aiocb.aio_offset = blknum * blocksize; aiocb.aio_cb = NULL; aiocb.data = NULL; /* If our buffer is unaligned or its aligned but we will need to rw a partial block * then a copy will have to be done */ if(!alignedbuf || blkoff != 0 || count % blocksize != 0) { copybuf = _xmalloc(blocksize, dev->info.sector_size); } rc = count; while(count > 0) { /* determine how many bytes to read/write from/to the current block buffer */ if(!alignedbuf || blkoff != 0 || count < blocksize) { /* This is the case for unaligned R/W or partial block */ bytes = count < blocksize - blkoff ? count : blocksize - blkoff; aiocb.aio_nbytes = blocksize; } else { /* We can optimize further if buffer is page aligned */ int not_page_aligned = 0; if(((uintptr_t)buf) & (PAGE_SIZE -1)) { not_page_aligned = 1; } /* For an aligned R/W we can read up to the maximum transfer size */ bytes = count > (BLKIF_MAX_SEGMENTS_PER_REQUEST-not_page_aligned)*PAGE_SIZE ? (BLKIF_MAX_SEGMENTS_PER_REQUEST-not_page_aligned)*PAGE_SIZE : count & ~(blocksize -1); aiocb.aio_nbytes = bytes; } /* read operation */ if(!write) { if (alignedbuf && bytes >= blocksize) { /* If aligned and were reading a whole block, just read right into buf */ aiocb.aio_buf = buf; blkfront_read(&aiocb); } else { /* If not then we have to do a copy */ aiocb.aio_buf = copybuf; blkfront_read(&aiocb); memcpy(buf, ©buf[blkoff], bytes); } } /* Write operation */ else { if(alignedbuf && bytes >= blocksize) { /* If aligned and were writing a whole block, just write directly from buf */ aiocb.aio_buf = buf; blkfront_write(&aiocb); } else { /* If not then we have to do a copy. */ aiocb.aio_buf = copybuf; /* If we're writing a partial block, we need to read the current contents first * so we don't overwrite the extra bits with garbage */ if(blkoff != 0 || bytes < blocksize) { blkfront_read(&aiocb); } memcpy(©buf[blkoff], buf, bytes); blkfront_write(&aiocb); } } /* Will start at beginning of all remaining blocks */ blkoff = 0; /* Increment counters and continue */ count -= bytes; buf += bytes; if(bytes < blocksize) { //At minimum we read one block aiocb.aio_offset += blocksize; } else { //If we read more than a block, was a multiple of blocksize aiocb.aio_offset += bytes; } } free(copybuf); files[fd].blk.offset += rc; return rc; }