Exemplo n.º 1
0
const char *test_mapping1(void)
{
	int rc;
	
	size_t buffer1_len = BUFFER1_PAGES * PAGE_SIZE;
	size_t buffer2_len = BUFFER2_PAGES * PAGE_SIZE;
	void *buffer1 = create_as_area(buffer1_len);
	void *buffer2 = create_as_area(buffer2_len);
	if (!buffer1 || !buffer2) {
		return "Cannot allocate memory";
	}
	
	touch_area(buffer1, buffer1_len);
	touch_area(buffer2, buffer2_len);
	
	/* Now verify that mapping to physical frames exist. */
	if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, EOK)) {
		return "Failed to find mapping (buffer1)";
	}
	if (!VERIFY_MAPPING(buffer2, BUFFER2_PAGES, EOK)) {
		return "Failed to find mapping (buffer2)";
	}
	
	/* Let's destroy the buffer1 area and access it again. */
	rc = as_area_destroy(buffer1);
	if (rc != EOK) {
		return "Failed to destroy AS area";
	}
	if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, ENOENT)) {
		return "Mapping of destroyed area still exists";
	}
	
	/* clean-up */
	rc = as_area_destroy(buffer2);
	if (rc != EOK) {
		return "Failed to destroy AS area";
	}
	
	return NULL;
}
Exemplo n.º 2
0
/** Create a program using an existing address space.
 *
 * @param as         Address space containing a binary program image.
 * @param entry_addr Program entry-point address in program address space.
 * @param name       Name to set for the program's task.
 * @param prg        Buffer for storing program information.
 *
 * @return EOK on success or negative error code.
 *
 */
int program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *prg)
{
	prg->loader_status = EE_OK;
	prg->task = task_create(as, name);
	if (!prg->task)
		return ELIMIT;
	
	/*
	 * Create the stack address space area.
	 */
	uintptr_t virt = USTACK_ADDRESS;
	as_area_t *area = as_area_create(as,
	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
	    STACK_SIZE, AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, 0);
	if (!area) {
		task_destroy(prg->task);
		return ENOMEM;
	}
	
	uspace_arg_t *kernel_uarg = (uspace_arg_t *)
	    malloc(sizeof(uspace_arg_t), 0);
	
	kernel_uarg->uspace_entry = (void *) entry_addr;
	kernel_uarg->uspace_stack = (void *) virt;
	kernel_uarg->uspace_stack_size = STACK_SIZE;
	kernel_uarg->uspace_thread_function = NULL;
	kernel_uarg->uspace_thread_arg = NULL;
	kernel_uarg->uspace_uarg = NULL;
	
	/*
	 * Create the main thread.
	 */
	prg->main_thread = thread_create(uinit, kernel_uarg, prg->task,
	    THREAD_FLAG_USPACE, "uinit");
	if (!prg->main_thread) {
		free(kernel_uarg);
		as_area_destroy(as, virt);
		task_destroy(prg->task);
		return ELIMIT;
	}
	
	return EOK;
}
Exemplo n.º 3
0
/** Get time of day
 *
 * The time variables are memory mapped (read-only) from kernel which
 * updates them periodically.
 *
 * As it is impossible to read 2 values atomically, we use a trick:
 * First we read the seconds, then we read the microseconds, then we
 * read the seconds again. If a second elapsed in the meantime, set
 * the microseconds to zero.
 *
 * This assures that the values returned by two subsequent calls
 * to gettimeofday() are monotonous.
 *
 */
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
	if (ktime == NULL) {
		uintptr_t faddr;
		int rc = sysinfo_get_value("clock.faddr", &faddr);
		if (rc != EOK) {
			errno = rc;
			return -1;
		}
		
		void *addr;
		rc = physmem_map((void *) faddr, 1,
		    AS_AREA_READ | AS_AREA_CACHEABLE, &addr);
		if (rc != EOK) {
			as_area_destroy(addr);
			errno = rc;
			return -1;
		}
		
		ktime = addr;
	}
	
	if (tz) {
		tz->tz_minuteswest = 0;
		tz->tz_dsttime = DST_NONE;
	}
	
	sysarg_t s2 = ktime->seconds2;
	
	read_barrier();
	tv->tv_usec = ktime->useconds;
	
	read_barrier();
	sysarg_t s1 = ktime->seconds1;
	
	if (s1 != s2) {
		tv->tv_sec = max(s1, s2);
		tv->tv_usec = 0;
	} else
		tv->tv_sec = s1;
	
	return 0;
}
Exemplo n.º 4
0
/** Try to shrink heap
 *
 * Should be called only inside the critical section.
 * In all cases the next pointer is reset.
 *
 * @param area Last modified heap area.
 *
 */
static void heap_shrink(heap_area_t *area)
{
	area_check(area);
	
	heap_block_foot_t *last_foot =
	    (heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area);
	heap_block_head_t *last_head = BLOCK_HEAD(last_foot);
	
	block_check((void *) last_head);
	malloc_assert(last_head->area == area);
	
	if (last_head->free) {
		/*
		 * The last block of the heap area is
		 * unused. The area might be potentially
		 * shrunk.
		 */
		
		heap_block_head_t *first_head =
		    (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(area);
		
		block_check((void *) first_head);
		malloc_assert(first_head->area == area);
		
		size_t shrink_size = ALIGN_DOWN(last_head->size, PAGE_SIZE);
		
		if (first_head == last_head) {
			/*
			 * The entire heap area consists of a single
			 * free heap block. This means we can get rid
			 * of it entirely.
			 */
			
			heap_area_t *prev = area->prev;
			heap_area_t *next = area->next;
			
			if (prev != NULL) {
				area_check(prev);
				prev->next = next;
			} else
				first_heap_area = next;
			
			if (next != NULL) {
				area_check(next);
				next->prev = prev;
			} else
				last_heap_area = prev;
			
			as_area_destroy(area->start);
		} else if (shrink_size >= SHRINK_GRANULARITY) {
			/*
			 * Make sure that we always shrink the area
			 * by a multiple of page size and update
			 * the block layout accordingly.
			 */
			
			size_t asize = (size_t) (area->end - area->start) - shrink_size;
			void *end = (void *) ((uintptr_t) area->start + asize);
			
			/* Resize the address space area */
			int ret = as_area_resize(area->start, asize, 0);
			if (ret != EOK)
				abort();
			
			/* Update heap area parameters */
			area->end = end;
			size_t excess = ((size_t) area->end) - ((size_t) last_head);
			
			if (excess > 0) {
				if (excess >= STRUCT_OVERHEAD) {
					/*
					 * The previous block cannot be free and there
					 * is enough free space left in the area to
					 * create a new free block.
					 */
					block_init((void *) last_head, excess, true, area);
				} else {
					/*
					 * The excess is small. Therefore just enlarge
					 * the previous block.
					 */
					heap_block_foot_t *prev_foot = (heap_block_foot_t *)
					    (((uintptr_t) last_head) - sizeof(heap_block_foot_t));
					heap_block_head_t *prev_head = BLOCK_HEAD(prev_foot);
					
					block_check((void *) prev_head);
					
					block_init(prev_head, prev_head->size + excess,
					    prev_head->free, area);
				}
			}
		}
	}
	
	next_fit = NULL;
}
Exemplo n.º 5
0
int ega_init(void)
{
	sysarg_t present;
	int rc = sysinfo_get_value("fb", &present);
	if (rc != EOK)
		present = false;
	
	if (!present)
		return ENOENT;
	
	sysarg_t kind;
	rc = sysinfo_get_value("fb.kind", &kind);
	if (rc != EOK)
		kind = (sysarg_t) -1;
	
	if (kind != 2)
		return EINVAL;
	
	sysarg_t paddr;
	rc = sysinfo_get_value("fb.address.physical", &paddr);
	if (rc != EOK)
		return rc;
	
	rc = sysinfo_get_value("fb.width", &ega.cols);
	if (rc != EOK)
		return rc;
	
	rc = sysinfo_get_value("fb.height", &ega.rows);
	if (rc != EOK)
		return rc;
	
	rc = pio_enable((void*)EGA_IO_BASE, EGA_IO_SIZE, NULL);
	if (rc != EOK)
		return rc;
	
	ega.size = (ega.cols * ega.rows) << 1;
	
	rc = physmem_map((void *) paddr,
	    ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
	    AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
	if (rc != EOK)
		return rc;
	
	sysarg_t blinking;
	rc = sysinfo_get_value("fb.blinking", &blinking);
	if (rc != EOK)
		blinking = false;
	
	ega.style_normal = 0xf0;
	ega.style_inverted = 0x0f;
	
	if (blinking) {
		ega.style_normal &= 0x77;
		ega.style_inverted &= 0x77;
	}
	
	outdev_t *dev = outdev_register(&ega_ops, (void *) &ega);
	if (dev == NULL) {
		as_area_destroy(ega.addr);
		return EINVAL;
	}
	
	return EOK;
}
Exemplo n.º 6
0
int munmap(void *start, size_t length)
{
	return as_area_destroy(start);
}
Exemplo n.º 7
0
/**
 * Record directly from a device to a file.
 * @param device The device.
 * @param file The file.
 * @return Error code.
 */
int drecord(const char *device, const char *file)
{
	int ret = EOK;
	audio_pcm_sess_t *session = NULL;
	if (str_cmp(device, "default") == 0) {
		session = audio_pcm_open_default();
	} else {
		session = audio_pcm_open(device);
	}
	if (!session) {
		printf("Failed to connect to device %s.\n", device);
		return 1;
	}
	printf("Recording on device: %s.\n", device);
	if (audio_pcm_query_cap(session, AUDIO_CAP_CAPTURE) <= 0) {
		printf("Device %s does not support recording\n", device);
		ret = ENOTSUP;
		goto close_session;
	}

	const char* info = NULL;
	ret = audio_pcm_get_info_str(session, &info);
	if (ret != EOK) {
		printf("Failed to get PCM info.\n");
		goto close_session;
	}
	printf("Capturing on %s.\n", info);
	free(info);

	record_t rec;
	record_initialize(&rec, session);

	ret = audio_pcm_get_buffer(rec.device, &rec.buffer.base,
	    &rec.buffer.size);
	if (ret != EOK) {
		printf("Failed to get PCM buffer: %s.\n", str_error(ret));
		goto close_session;
	}
	printf("Buffer: %p %zu.\n", rec.buffer.base, rec.buffer.size);

	rec.file = fopen(file, "w");
	if (rec.file == NULL) {
		ret = ENOENT;
		printf("Failed to open file: %s.\n", file);
		goto cleanup;
	}

	wave_header_t header;
	fseek(rec.file, sizeof(header), SEEK_SET);
	if (ret != EOK) {
		printf("Error parsing wav header\n");
		goto cleanup;
	}
	if (audio_pcm_query_cap(rec.device, AUDIO_CAP_INTERRUPT) > 0)
		record_fragment(&rec, format);
	else
		printf("Recording method is not supported");
	//TODO consider buffer position interface

	wav_init_header(&header, format, ftell(rec.file) - sizeof(header));
	fseek(rec.file, 0, SEEK_SET);
	fwrite(&header, sizeof(header), 1, rec.file);

cleanup:
	fclose(rec.file);
	as_area_destroy(rec.buffer.base);
	audio_pcm_release_buffer(rec.device);
close_session:
	audio_pcm_close(session);
	return ret == EOK ? 0 : 1;
}