void GrowBuffer(WriteBuffer* buf, int size) { if (buf->len + size > buf->size) { int newsize = max(buf->size * 2, buf->len + size); if (buf->buffer != buf->prealloc) buf->buffer = MEM_REALLOC(buf->buffer, newsize); else { buf->buffer = MEM_ALLOC(newsize); memcpy(buf->buffer, buf->prealloc, sizeof(buf->prealloc)); } buf->size = newsize; } }
Handle *dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly, int *result, int *status ){ /* Local Variables; */ Handle *child; int ichild; int top_level; pthread_t *locker; pthread_t *rlocker; int i; int j; Handle *error_handle = NULL; int child_result; /* initialise */ *result = 0; /* Check inherited status. */ if( *status != SAI__OK ) return error_handle; /* Validate the supplied Handle */ if( !dat1ValidateHandle( "dat1HandleLock", handle, status ) ) return error_handle; /* To avoid deadlocks, we only lock the Handle mutex for top level entries to this function. If "oper" is negative, negate it and set a flag indicating we do not need to lock the mutex. */ if( oper < 0 ) { oper = -oper; top_level = 0; } else { top_level = 1; } /* For top-level entries to this function, we need to ensure no other thread is modifying the details in the handle, so attempt to lock the handle's mutex. */ if( top_level ) pthread_mutex_lock( &(handle->mutex) ); /* Return information about the current lock on the supplied Handle. ------------------------------------------------------------------ */ if( oper == 1 ) { /* Default: unlocked */ if( handle->nwrite_lock ) { if( pthread_equal( handle->write_locker, pthread_self() )) { /* Locked for writing by the current thread. */ *result = 1; } else { /* Locked for writing by another thread. */ *result = 2; } } else if( handle->nread_lock ){ /* Locked for reading by one or more other threads (the current thread does not have a read lock on the Handle). */ *result = 4; /* Now check to see if the current thread has a read lock, changing the above result value if it does. */ locker = handle->read_lockers; for( i = 0; i < handle->nread_lock;i++,locker++ ) { if( pthread_equal( *locker, pthread_self() )) { /* Locked for reading by the current thread (other threads may also have a read lock on the Handle). */ *result = 3; break; } } } /* If required, check any child handles. If we already have a status of 2, (the supplied handle is locked read-write by another thread), we do not need to check the children. */ if( recurs && *result != 2 ){ for( ichild = 0; ichild < handle->nchild; ichild++ ) { child = handle->children[ichild]; if( child ) { /* Get the lock status of the child. */ (void) dat1HandleLock( child, -1, 1, rdonly, &child_result, status ); /* If it's 2, we can set the final result and exit immediately. */ if( child_result == 2 ) { *result = 2; break; /* Otherwise, ensure the child gives the same result as all the others, breaking out and returning the catch-all value if not. */ } else if( child_result != *result ) { *result = 5; break; } } } } /* Lock the handle for use by the current thread. ------------------------------------------------------------------ */ } else if( oper == 2 ) { /* A read-only lock requested.... */ if( rdonly ) { /* If the current thread has a read-write lock on the Handle, demote it to a read-only lock and return 1 (success). In this case, we know there will be no other read-locks. Otherwise if any other thread has read-write lock, return zero (failure). */ if( handle->nwrite_lock ) { if( pthread_equal( handle->write_locker, pthread_self() )) { /* If we do not have an array in which to store read lock thread IDs, allocate one now with room for NTHREAD locks. It will be extended as needed. */ if( !handle->read_lockers ) { handle->read_lockers = MEM_CALLOC(NTHREAD,sizeof(pthread_t)); if( !handle->read_lockers ) { *status = DAT__NOMEM; emsRep( "", "Could not allocate memory for HDS " "Handle read locks list.", status ); } } /* If we now have an array, store the current thread in the first element. */ if( handle->read_lockers ) { handle->read_lockers[ 0 ] = pthread_self(); handle->nread_lock = 1; handle->nwrite_lock = 0; *result = 1; } } /* If there is no read-write lock on the Handle, add the current thread to the list of threads that currently have a read-only lock, but only if it is not already there. */ } else { /* Set "result" to 1 if the current thread already has a read-only lock. */ locker = handle->read_lockers; for( i = 0; i < handle->nread_lock;i++,locker++ ) { if( pthread_equal( *locker, pthread_self() )) { *result = 1; break; } } /* If not, extend the read lock thread ID array if necessary, and append the current thread ID to the end. */ if( *result == 0 ) { handle->nread_lock++; if( handle->maxreaders < handle->nread_lock ) { handle->maxreaders += NTHREAD; handle->read_lockers = MEM_REALLOC( handle->read_lockers, handle->maxreaders*sizeof(pthread_t)); if( !handle->read_lockers ) { *status = DAT__NOMEM; emsRep( "", "Could not reallocate memory for HDS " "Handle read locks list.", status ); } } if( handle->read_lockers ) { handle->read_lockers[ handle->nread_lock - 1 ] = pthread_self(); /* Indicate the read-only lock was applied successfully. */ *result = 1; } } } /* A read-write lock requested. */ } else { /* If there are currently no locks of any kind, apply the lock. */ if( handle->nread_lock == 0 ) { if( handle->nwrite_lock == 0 ) { handle->write_locker = pthread_self(); handle->nwrite_lock = 1; *result = 1; /* If the current thread already has a read-write lock, indicate success. */ } else if( pthread_equal( handle->write_locker, pthread_self() )) { *result = 1; } /* If there is currently only one read-only lock, and it is owned by the current thread, then promote it to a read-write lock. */ } else if( handle->nread_lock == 1 && pthread_equal( handle->read_lockers[0], pthread_self() )) { handle->nread_lock = 0; handle->write_locker = pthread_self(); handle->nwrite_lock = 1; *result = 1; } } /* If required, and if the above lock operation was successful, lock any child handles that can be locked. */ if( *result ){ if( recurs ){ for( ichild = 0; ichild < handle->nchild; ichild++ ) { child = handle->children[ichild]; if( child ) { error_handle = dat1HandleLock( child, -2, 1, rdonly, result, status ); if( error_handle ) break; } } } /* If the lock operation failed, return a pointer to the Handle. */ } else { error_handle = handle; } /* Unlock the handle. ----------------- */ } else if( oper == 3 ) { /* Assume failure. */ *result = 0; /* If the current thread has a read-write lock, remove it. */ if( handle->nwrite_lock ) { if( pthread_equal( handle->write_locker, pthread_self() )) { handle->nwrite_lock = 0; *result = 1; } else { *result = -1; } /* Otherwise, if the current thread has a read-only lock, remove it. */ } else { /* Loop through all the threads that have read-only locks. */ locker = handle->read_lockers; for( i = 0; i < handle->nread_lock; i++,locker++ ) { /* If the current thread is found, shuffle any remaining threads down one slot to fill the gap left by removing the current thread from the list. */ if( pthread_equal( *locker, pthread_self() )) { rlocker = locker + 1; for( j = i + 1; j < handle->nread_lock; j++,locker++ ) { *locker = *(rlocker++); } /* Reduce the number of read-only locks. */ handle->nread_lock--; *result = 1; break; } } } /* If required, and if the above unlock operation was successful, unlock any child handles that can be unlocked. */ if( *result == 1 ){ if( recurs ){ for( ichild = 0; ichild < handle->nchild; ichild++ ) { child = handle->children[ichild]; if( child ) { error_handle = dat1HandleLock( child, -3, 1, 0, result, status ); if( error_handle ) break; } } } /* If the unlock operation failed, return a pointer to the Handle. */ } else { error_handle = handle; } /* Report an error for any other "oper" value. */ } else if( *status == SAI__OK ) { *status = DAT__FATAL; emsRepf( " ", "dat1HandleLock: Unknown 'oper' value (%d) supplied - " "(internal HDS programming error).", status, oper ); } /* If this is a top-level entry, unlock the Handle's mutex so that other threads can access the values in the Handle. */ if( top_level ) pthread_mutex_unlock( &(handle->mutex) ); /* Return the error handle. */ return error_handle; }
static void regular_test(struct mem_allocator* allocator) { char dump[BUFSIZ]; void* p = NULL; void* q[3] = {NULL, NULL, NULL}; size_t i = 0; p = MEM_ALIGNED_ALLOC(allocator, 1024, ALIGNOF(char)); NCHECK(p, NULL); CHECK(IS_ALIGNED((uintptr_t)p, ALIGNOF(char)), 1); MEM_FREE(allocator, p); q[0] = MEM_ALIGNED_ALLOC(allocator, 10, 8); q[1] = MEM_CALLOC(allocator, 1, 58); q[2] = MEM_ALLOC(allocator, 78); NCHECK(q[0], NULL); NCHECK(q[1], NULL); NCHECK(q[2], NULL); CHECK(IS_ALIGNED((uintptr_t)q[0], 8), 1); p = MEM_CALLOC(allocator, 2, 2); NCHECK(p, NULL); for(i = 0; i < 4; ++i) CHECK(((char*)p)[i], 0); for(i = 0; i < 4; ++i) ((char*)p)[i] = (char)i; MEM_DUMP(allocator, dump, BUFSIZ); printf("dump:\n%s\n", dump); MEM_DUMP(allocator, dump, 16); printf("truncated dump:\n%s\n", dump); MEM_DUMP(allocator, NULL, 0); /* may not crashed. */ MEM_FREE(allocator, q[1]); p = MEM_REALLOC(allocator, p, 8); for(i = 0; i < 4; ++i) CHECK(((char*)p)[i], (char)i); for(i = 4; i < 8; ++i) ((char*)p)[i] = (char)i; MEM_FREE(allocator, q[2]); p = MEM_REALLOC(allocator, p, 5); for(i = 0; i < 5; ++i) CHECK(((char*)p)[i], (char)i); MEM_FREE(allocator, p); p = NULL; p = MEM_REALLOC(allocator, NULL, 16); NCHECK(p, NULL); p = MEM_REALLOC(allocator, p, 0); MEM_FREE(allocator, q[0]); CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 0), NULL); CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 3), NULL); CHECK(MEM_ALLOCATED_SIZE(allocator), 0); }
void video_draw_rect_rotated(TexHandle tex, uint layer, const RectF* source, const RectF* dest, float rotation, Color tint) { assert(layer < bucket_count); assert(dest); assert(tex < textures.size); Texture* t = DARRAY_DATA_PTR(textures, Texture); assert(t[tex].active); uint fixed_scale = (uint)(t[tex].scale * (tex_mul+1.0f)); uint texture_width = t[tex].width; uint texture_height = t[tex].height; int16 real_src_l = 0; int16 real_src_t = 0; int16 real_src_r = texture_width; int16 real_src_b = texture_height; if(source != NULL) { real_src_l = (int16)(source->left); real_src_t = (int16)(source->top); real_src_r = (int16)(source->right); real_src_b = (int16)(source->bottom); } // This is faster than comparing floats bool full_dest = (*((uint*)&dest->right) | *((uint*)&dest->bottom)) == 0U; RectF real_dest = *dest; int w = real_src_r - real_src_l; int h = real_src_b - real_src_t; if(full_dest) { float width = (float)w; float height = (float)h; real_dest.right = real_dest.left + width; real_dest.bottom = real_dest.top + height; } // Don't draw rect if it's not inside screen rect if(transform[layer] == NULL) { RectF screen = {0.0f, 0.0f, screen_widthf, screen_heightf}; if(!rectf_rectf_collision(&screen, &real_dest)) return; } assert(is_pow2((texture_width * fixed_scale) >> 15)); assert(is_pow2((texture_height * fixed_scale) >> 15)); uint wlog2 = _ilog2((texture_width * fixed_scale) >> 15); uint hlog2 = _ilog2((texture_height * fixed_scale) >> 15); real_src_l = ((real_src_l << 15) - 1) >> wlog2; real_src_t = ((real_src_t << 15) - 1) >> hlog2; real_src_r = ((real_src_r << 15) - 1) >> wlog2; real_src_b = ((real_src_b << 15) - 1) >> hlog2; TexturedRectDesc new_rect = { .tex = tex, .src_l = real_src_l, .src_t = real_src_t, .src_r = real_src_r, .src_b = real_src_b, .dest = real_dest, .tint = tint, .rotation = rotation }; // Do something uglier instead of darray_append, saving a memcpy here is worth it //darray_append(&rect_buckets[layer], &new_rect); DArray* bucket = &rect_buckets[layer]; if(!bucket->reserved) rect_buckets[layer] = darray_create(sizeof(TexturedRectDesc), 32); else if(bucket->reserved - bucket->size < 1) { bucket->reserved *= 2; bucket->data = MEM_REALLOC(bucket->data, bucket->item_size * bucket->reserved); } TexturedRectDesc* rects = DARRAY_DATA_PTR(*bucket, TexturedRectDesc); rects[bucket->size] = new_rect; bucket->size++; }
int main(int argc, char** argv) { char buf[BUFSIZ]; struct font_glyph_desc desc; struct font_system* sys = NULL; struct font_rsrc* font = NULL; struct font_glyph* glyph = NULL; const char* path = NULL; unsigned char* buffer = NULL; size_t buffer_size = 0; int h = 0; int w = 0; int Bpp = 0; int i = 0; bool b = false; if(argc != 2) { printf("usage: %s FONT\n", argv[0]); goto error; } path = argv[1]; CHECK(font_system_create( NULL, NULL ), BAD_ARG); CHECK(font_system_create(NULL, &sys), OK); CHECK(font_rsrc_create(NULL, NULL, NULL), BAD_ARG); CHECK(font_rsrc_create(sys, NULL, NULL), BAD_ARG); CHECK(font_rsrc_create(NULL, NULL, &font), BAD_ARG); CHECK(font_rsrc_create(sys, NULL, &font), OK); CHECK(font_rsrc_load(NULL, NULL), BAD_ARG); CHECK(font_rsrc_load(font, NULL), BAD_ARG); CHECK(font_rsrc_load(NULL, path), BAD_ARG); CHECK(font_rsrc_load(font, path), OK); CHECK(font_rsrc_is_scalable(NULL, NULL), BAD_ARG); CHECK(font_rsrc_is_scalable(font, NULL), BAD_ARG); CHECK(font_rsrc_is_scalable(NULL, &b), BAD_ARG); CHECK(font_rsrc_is_scalable(font, &b), OK); if(b) { CHECK(font_rsrc_set_size(NULL, 0, 0), BAD_ARG); CHECK(font_rsrc_set_size(font, 0, 0), BAD_ARG); CHECK(font_rsrc_set_size(NULL, 32, 0), BAD_ARG); CHECK(font_rsrc_set_size(font, 32, 0), BAD_ARG); CHECK(font_rsrc_set_size(NULL, 0, 64), BAD_ARG); CHECK(font_rsrc_set_size(font, 0, 64), BAD_ARG); CHECK(font_rsrc_set_size(NULL, 32, 64), BAD_ARG); CHECK(font_rsrc_set_size(font, 32, 64), OK); CHECK(font_rsrc_set_size(font, 16, 16), OK); } CHECK(font_rsrc_get_line_space(NULL, NULL), BAD_ARG); CHECK(font_rsrc_get_line_space(font, NULL), BAD_ARG); CHECK(font_rsrc_get_line_space(NULL, &i), BAD_ARG); CHECK(font_rsrc_get_line_space(font, &i), OK); CHECK(font_rsrc_get_glyph(NULL, L'a', NULL), BAD_ARG); CHECK(font_rsrc_get_glyph(font, L'a', NULL), BAD_ARG); CHECK(font_rsrc_get_glyph(NULL, L'a', &glyph), BAD_ARG); CHECK(font_rsrc_get_glyph(font, L'a', &glyph), OK); CHECK(font_glyph_get_desc(NULL, NULL), BAD_ARG); CHECK(font_glyph_get_desc(glyph, NULL), BAD_ARG); CHECK(font_glyph_get_desc(NULL, &desc), BAD_ARG); CHECK(font_glyph_get_desc(glyph, &desc), OK); CHECK(desc.character, L'a'); CHECK(font_glyph_get_bitmap(NULL, true, NULL, NULL, NULL, NULL), BAD_ARG); CHECK(font_glyph_get_bitmap(glyph, true, NULL, NULL, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, NULL, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, NULL, &h, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, NULL, NULL, &Bpp, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, NULL, &Bpp, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, NULL, &h, &Bpp, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, &Bpp, NULL), OK); NCHECK(w, 0); NCHECK(h, 0); NCHECK(Bpp, 0); buffer = MEM_CALLOC (&mem_default_allocator, (size_t)(w*h*Bpp), sizeof(unsigned char)); NCHECK(buffer, NULL); buffer_size = (size_t)(w*h*Bpp) * sizeof(unsigned char); CHECK(font_glyph_get_bitmap(glyph, false, NULL, NULL, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, NULL, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, NULL, &h, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, &h, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, NULL, NULL, &Bpp, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, NULL, &Bpp, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, NULL, &h, &Bpp, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, &h, &Bpp, buffer), OK); CHECK(font_glyph_ref_get(NULL), BAD_ARG); CHECK(font_glyph_ref_get(glyph), OK); CHECK(font_glyph_ref_put(NULL), BAD_ARG); CHECK(font_glyph_ref_put(glyph), OK); CHECK(font_glyph_ref_put(glyph), OK); b = true; for(i = 0; b && i < w*h*Bpp; ++i) b = ((int)buffer[i] == 0); CHECK(b, false); for(i = 32; i < 127; ++i) { size_t required_buffer_size = 0; CHECK(font_rsrc_get_glyph(font, (wchar_t)i, &glyph), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, &Bpp, NULL), OK); required_buffer_size = (size_t)(w * h * Bpp) * sizeof(unsigned char); if(required_buffer_size > buffer_size) { buffer = MEM_REALLOC(&mem_default_allocator,buffer, required_buffer_size); NCHECK(buffer, NULL); buffer_size = required_buffer_size; } CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, &Bpp, buffer), OK); NCHECK(snprintf(buf, BUFSIZ, "/tmp/%.3d.ppm", i - 32), BUFSIZ); CHECK(image_ppm_write(buf, w, h, Bpp, buffer), 0); CHECK(font_glyph_ref_put(glyph), OK); } MEM_FREE(&mem_default_allocator, buffer); CHECK(font_rsrc_ref_get(NULL), BAD_ARG); CHECK(font_rsrc_ref_get(font), OK); CHECK(font_rsrc_ref_put(NULL), BAD_ARG); CHECK(font_rsrc_ref_put(font), OK); CHECK(font_rsrc_ref_put(font), OK); CHECK(font_system_ref_get(NULL), BAD_ARG); CHECK(font_system_ref_get(sys), OK); CHECK(font_system_ref_put(NULL), BAD_ARG); CHECK(font_system_ref_put(sys), OK); CHECK(font_system_ref_put(sys), OK); CHECK(MEM_ALLOCATED_SIZE(&mem_default_allocator), 0); return 0; error: return -1; }