aboutsummaryrefslogtreecommitdiffstats
path: root/include/litmus/dgl.h
blob: e405a936bf7f687c6150b332b87b640b021b9aee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#ifndef __DGL_H_
#define __DGL_H_
/**
 * TODO: reduce size of types
 */

#include <litmus/color.h>
#include <linux/list.h>

struct dgl;
struct dgl_group_req;

typedef void (*acquired_t)(struct dgl_group_req *greq);
typedef void (*preempted_t)(struct dgl_group_req *greq);
typedef unsigned long long (*prio_t)(struct dgl *dgl,
				     struct dgl_group_req *greq);

/*
 * A request for @replica amount of a single resource.
 */
struct dgl_req {
	struct dgl_group_req	*greq;
	unsigned short 		replicas;

	struct list_head 	list;
};

/*
 * Simultaneous @requests for multiple resources.
 */
struct dgl_group_req {
	unsigned int 		cpu;

	/* Request status flags */
	unsigned long 		*requested; /* Resources requested       */
	unsigned long		*need_prio; /* Resources it can't take   */
	unsigned long 		*blocked;

	/* TODO: use bitops to reduce number of requests to only needed,
	 * get index by counting number of 1s up to a point
	 */
	struct dgl_req	 	*requests;

	/* Request priority in lists */
	unsigned long long	priority;
	struct task_struct	*task;  /* Tie-breaking */
};

/*
 * A single resource.
 */
struct dgl_resource {
	int 			goal_free;
	int			real_free;

	/* Requests whose group requests don't have priority on all replicas.
	 * group request state: need_prio && dgl->acquired[cpu] != greq
	 */
	struct list_head 	waiting;      /* Hi-to-lo */
	/* Requests whose group requests no longer have priority, but currently
	 * hold all resources.
	 * group request state: need_prio && dgl->acquired[cpu] == greq
	 */
	struct list_head	will_wait;    /* Hi-to-lo */
	/* Requests whose group requests both have priority and hold all
	 * requested resources.
	 * group request state: !need_prio && !blocking && acquired[cpu] == greq
	 */
	struct list_head        acquired;     /* Lo-to-hi */
	/* Requests whose group requests have priority but are blocked from
	 * acquiring some resource.
	 * group request state: need_prio && blocking && acquired[cpu] != greq
	 */
	struct list_head	will_acquire; /* Lo-to-hi */
};

/*
 * A group of resources.
 */
struct dgl {
	struct dgl_resource 	*resources;
	struct dgl_group_req* 	*acquired;

	int 			requests;
	unsigned long long	ts;

	unsigned long           num_resources;
	unsigned long		num_replicas;

	/* A group request now owns all of its resources */
	acquired_t		cpu_acquired;
	/* Assign priority (lower is better) to a group request */
	prio_t			assign_priority;
	/* Called when a request is preempted. Leave at NULL for no calls */
	preempted_t		cpu_preempted;
};

void dgl_init(struct dgl *dgl, unsigned long num_resources,
	      unsigned long num_replicas);
void dgl_free(struct dgl *dgl);

void dgl_group_req_init(struct dgl *dgl, struct dgl_group_req *greq);
void dgl_group_req_free(struct dgl_group_req *greq);

void set_req(struct dgl *dgl, struct dgl_group_req *greq,
	     int resource, int replicas);

void add_group_req(struct dgl *dgl, struct dgl_group_req *greq, int cpu);
void remove_group_req(struct dgl *dgl, struct dgl_group_req *greq);
void update_group_req(struct dgl *dgl, struct dgl_group_req *greq);

#endif