| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 | 
							- /* StarPU --- Runtime system for heterogeneous multicore architectures.
 
-  *
 
-  * Copyright (C) 2012-2020  Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
 
-  *
 
-  * StarPU is free software; you can redistribute it and/or modify
 
-  * it under the terms of the GNU Lesser General Public License as published by
 
-  * the Free Software Foundation; either version 2.1 of the License, or (at
 
-  * your option) any later version.
 
-  *
 
-  * StarPU is distributed in the hope that it will be useful, but
 
-  * WITHOUT ANY WARRANTY; without even the implied warranty of
 
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
-  *
 
-  * See the GNU Lesser General Public License in COPYING.LGPL for more details.
 
-  */
 
- #include <starpu.h>
 
- #include <common/utils.h>
 
- #include <common/thread.h>
 
- #include <common/fxt.h>
 
- #include <datawizard/memory_manager.h>
 
- #include <datawizard/memory_nodes.h>
 
- #include <core/workers.h>
 
- #include <starpu_stdlib.h>
 
- static size_t global_size[STARPU_MAXNODES];
 
- static size_t used_size[STARPU_MAXNODES];
 
- /* This is used as an optimization to avoid to wake up allocating threads for
 
-  * each and every deallocation, only to find that there is still not enough
 
-  * room.  */
 
- /* Minimum amount being waited for */
 
- static size_t waiting_size[STARPU_MAXNODES];
 
- static starpu_pthread_mutex_t lock_nodes[STARPU_MAXNODES];
 
- static starpu_pthread_cond_t cond_nodes[STARPU_MAXNODES];
 
- int _starpu_memory_manager_init()
 
- {
 
- 	int i;
 
- 	for(i=0 ; i<STARPU_MAXNODES ; i++)
 
- 	{
 
- 		global_size[i] = 0;
 
- 		used_size[i] = 0;
 
- 		/* This is accessed for statistics outside the lock, don't care
 
- 		 * about that */
 
- 		STARPU_HG_DISABLE_CHECKING(used_size[i]);
 
- 		STARPU_HG_DISABLE_CHECKING(global_size[i]);
 
- 		waiting_size[i] = 0;
 
- 		STARPU_PTHREAD_MUTEX_INIT(&lock_nodes[i], NULL);
 
- 		STARPU_PTHREAD_COND_INIT(&cond_nodes[i], NULL);
 
- 	}
 
- 	return 0;
 
- }
 
- void _starpu_memory_manager_set_global_memory_size(unsigned node, size_t size)
 
- {
 
- 	STARPU_PTHREAD_MUTEX_LOCK(&lock_nodes[node]);
 
- 	if (!global_size[node])
 
- 	{
 
- 		global_size[node] = size;
 
- 		_STARPU_DEBUG("Global size for node %u is %ld\n", node, (long)global_size[node]);
 
- 	}
 
- 	else
 
- 	{
 
- 		STARPU_ASSERT(global_size[node] == size);
 
- 	}
 
- 	STARPU_PTHREAD_MUTEX_UNLOCK(&lock_nodes[node]);
 
- }
 
- size_t _starpu_memory_manager_get_global_memory_size(unsigned node)
 
- {
 
- 	return global_size[node];
 
- }
 
- int starpu_memory_allocate(unsigned node, size_t size, int flags)
 
- {
 
- 	int ret;
 
- 	STARPU_PTHREAD_MUTEX_LOCK(&lock_nodes[node]);
 
- 	if (flags & STARPU_MEMORY_WAIT)
 
- 	{
 
- 		struct _starpu_worker *worker = _starpu_get_local_worker_key();
 
- 		enum _starpu_worker_status old_status = STATUS_UNKNOWN;
 
- 		if (worker)
 
- 		{
 
- 			old_status = worker->status;
 
- 			_starpu_set_worker_status(worker, STATUS_WAITING);
 
- 		}
 
- 		while (used_size[node] + size > global_size[node])
 
- 		{
 
- 			/* Tell deallocators we need this amount */
 
- 			if (!waiting_size[node] || size < waiting_size[node])
 
- 				waiting_size[node] = size;
 
- 			/* Wait for it */
 
- 			STARPU_PTHREAD_COND_WAIT(&cond_nodes[node], &lock_nodes[node]);
 
- 		}
 
- 		if (worker)
 
- 		{
 
- 			_starpu_set_worker_status(worker, old_status);
 
- 		}
 
- 		/* And take it */
 
- 		used_size[node] += size;
 
- 		_STARPU_TRACE_USED_MEM(node, used_size[node]);
 
- 		ret = 0;
 
- 	}
 
- 	else if (flags & STARPU_MEMORY_OVERFLOW
 
- 			|| global_size[node] == 0
 
- 			|| used_size[node] + size <= global_size[node])
 
- 	{
 
- 		used_size[node] += size;
 
- 		_STARPU_TRACE_USED_MEM(node, used_size[node]);
 
- 		ret = 0;
 
- 	}
 
- 	else
 
- 	{
 
- 		ret = -ENOMEM;
 
- 	}
 
- 	STARPU_PTHREAD_MUTEX_UNLOCK(&lock_nodes[node]);
 
- 	return ret;
 
- }
 
- void starpu_memory_deallocate(unsigned node, size_t size)
 
- {
 
- 	STARPU_PTHREAD_MUTEX_LOCK(&lock_nodes[node]);
 
- 	used_size[node] -= size;
 
- 	_STARPU_TRACE_USED_MEM(node, used_size[node]);
 
- 	/* If there's now room for waiters, wake them */
 
- 	if (waiting_size[node] &&
 
- 		global_size[node] - used_size[node] >= waiting_size[node])
 
- 	{
 
- 		/* And have those not happy enough tell us the size again */
 
- 		waiting_size[node] = 0;
 
- 		STARPU_PTHREAD_COND_BROADCAST(&cond_nodes[node]);
 
- 	}
 
- 	STARPU_PTHREAD_MUTEX_UNLOCK(&lock_nodes[node]);
 
- }
 
- starpu_ssize_t starpu_memory_get_total(unsigned node)
 
- {
 
- 	if (global_size[node] == 0)
 
- 		return -1;
 
- 	else
 
- 		return global_size[node];
 
- }
 
- starpu_ssize_t starpu_memory_get_total_all_nodes()
 
- {
 
- 	unsigned memnodes, i;
 
- 	memnodes = starpu_memory_nodes_get_count();
 
- 	starpu_ssize_t total = 0;
 
- 	for(i=0 ; i<memnodes ; i++)
 
- 	{
 
- 		starpu_ssize_t node = starpu_memory_get_total(i);
 
- 		if (node != -1)
 
- 			total += node;
 
- 	}
 
- 	return total;
 
- }
 
- starpu_ssize_t starpu_memory_get_available(unsigned node)
 
- {
 
- 	starpu_ssize_t ret;
 
- 	if (global_size[node] == 0)
 
- 		return -1;
 
- 	ret = global_size[node] - used_size[node];
 
- 	return ret;
 
- }
 
- starpu_ssize_t starpu_memory_get_available_all_nodes()
 
- {
 
- 	unsigned memnodes, i;
 
- 	memnodes = starpu_memory_nodes_get_count();
 
- 	starpu_ssize_t avail = 0;
 
- 	for(i=0 ; i<memnodes ; i++)
 
- 	{
 
- 		starpu_ssize_t node = starpu_memory_get_available(i);
 
- 		if (node != -1)
 
- 			avail += node;
 
- 	}
 
- 	return avail;
 
- }
 
- void starpu_memory_wait_available(unsigned node, size_t size)
 
- {
 
- 	STARPU_PTHREAD_MUTEX_LOCK(&lock_nodes[node]);
 
- 	while (used_size[node] + size > global_size[node])
 
- 	{
 
- 		/* Tell deallocators we need this amount */
 
- 		if (!waiting_size[node] || size < waiting_size[node])
 
- 			waiting_size[node] = size;
 
- 		/* Wait for it */
 
- 		STARPU_PTHREAD_COND_WAIT(&cond_nodes[node], &lock_nodes[node]);
 
- 	}
 
- 	STARPU_PTHREAD_MUTEX_UNLOCK(&lock_nodes[node]);
 
- }
 
- int _starpu_memory_manager_test_allocate_size(unsigned node, size_t size)
 
- {
 
- 	int ret;
 
- 	if (global_size[node] == 0)
 
- 		ret = 1;
 
- 	else if (used_size[node] + size <= global_size[node])
 
- 		ret = 1;
 
- 	else
 
- 		ret = 0;
 
- 	return ret;
 
- }
 
 
  |