Sched flag refactoring. Implemented wqCPUX, QUEUEX. RW lock refactoring for KQDOM and KVLST
This commit is contained in:
parent
f085e08d18
commit
caba92060d
File diff suppressed because it is too large
Load Diff
@ -395,13 +395,25 @@ __END_DECLS
|
|||||||
* The ioctl to set multithreaded mode
|
* The ioctl to set multithreaded mode
|
||||||
*/
|
*/
|
||||||
#define FKQMULTI _IOW('f', 89, int)
|
#define FKQMULTI _IOW('f', 89, int)
|
||||||
|
#define FKQMPRNT _IO('f', 90)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* KQ scheduler flags
|
* KQ sched
|
||||||
*/
|
*/
|
||||||
#define KQ_SCHED_WS 0x01
|
#define KQ_SCHED_QUEUE 0x01 /* affnitizes knotes to the current cpu, sarg = extra queues to check */
|
||||||
#define KQ_SCHED_QUEUE 0x02 /* make kq affinitize the knote depending on the first cpu it's scheduled to */
|
#define KQ_SCHED_CPU 0x02 /* affinitize knotes to the first cpu, sarg = extra queues to check */
|
||||||
#define KQ_SCHED_CPU 0x04 /* make kq affinitize the knote depending on the runtime cpu it's scheduled to */
|
#define KQ_SCHED_BEST 0x04 /* Best of N, sarg = N */
|
||||||
#define KQ_SCHED_BOT 0x08
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KQ sched flags
|
||||||
|
*/
|
||||||
|
#define KQ_SCHED_FLAG_WS 0x01 /* work stealing, farg = # of knotes to steal */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0 - 7: sched
|
||||||
|
* 8 - 15: sargs
|
||||||
|
* 16 - 23: flags
|
||||||
|
* 24 - 31: fargs
|
||||||
|
*/
|
||||||
|
#define KQSCHED_MAKE(sched, sargs, flags, fargs) (((sched) & 0xFF) | (((sargs) & 0xFF) << 8) | (((flags) & 0xFF) << 16) | (((fargs) & 0xFF) << 24))
|
||||||
#endif /* !_SYS_EVENT_H_ */
|
#endif /* !_SYS_EVENT_H_ */
|
||||||
|
@ -45,7 +45,6 @@
|
|||||||
#define KQ_NEVENTS 8 /* minimize copy{in,out} calls */
|
#define KQ_NEVENTS 8 /* minimize copy{in,out} calls */
|
||||||
#define KQEXTENT 256 /* linear growth by this amount */
|
#define KQEXTENT 256 /* linear growth by this amount */
|
||||||
|
|
||||||
#define KQDOM_EXTENT 8 /* linear growth by this amount */
|
|
||||||
#define KQDIR_ACTIVE (0)
|
#define KQDIR_ACTIVE (0)
|
||||||
#define KQDIR_INACTIVE (1)
|
#define KQDIR_INACTIVE (1)
|
||||||
|
|
||||||
@ -55,19 +54,20 @@ struct kevq {
|
|||||||
LIST_ENTRY(kevq) kevq_th_tqe; /* entry into kevq_thred's kevq_list */
|
LIST_ENTRY(kevq) kevq_th_tqe; /* entry into kevq_thred's kevq_list */
|
||||||
struct kqueue *kq; /* the kq that the kevq belongs to */
|
struct kqueue *kq; /* the kq that the kevq belongs to */
|
||||||
struct kqdom *kevq_kqd; /* the kq domain the kevq is on */
|
struct kqdom *kevq_kqd; /* the kq domain the kevq is on */
|
||||||
|
/* XXX: Make kevq contain a struct thread ptr instead of this dude */
|
||||||
struct kevq_thred *kevq_th; /* the thread that the kevq belongs to */
|
struct kevq_thred *kevq_th; /* the thread that the kevq belongs to */
|
||||||
struct mtx lock; /* the lock for the kevq */
|
struct mtx lock; /* the lock for the kevq */
|
||||||
TAILQ_HEAD(, knote) kn_head; /* list of pending knotes */
|
TAILQ_HEAD(, knote) kn_head; /* list of pending knotes */
|
||||||
int kn_count; /* number of pending knotes */
|
int kn_count; /* number of pending knotes */
|
||||||
#define KEVQ_SLEEP 0x01
|
#define KEVQ_SLEEP 0x01
|
||||||
#define KEVQ_CLOSING 0x02
|
#define KEVQ_CLOSING 0x02
|
||||||
#define KEVQ_RDY 0x04
|
#define KEVQ_ACTIVE 0x04
|
||||||
int kevq_state;
|
int kevq_state;
|
||||||
int kevq_refcnt;
|
int kevq_refcnt;
|
||||||
|
|
||||||
/* Used by the scheduler */
|
/* Used by the scheduler */
|
||||||
unsigned long kevq_avg_lat;
|
uint64_t kevq_avg_lat;
|
||||||
struct timespec kevq_last_kev;
|
uint64_t kevq_last_kev;
|
||||||
uint64_t kevq_last_nkev;
|
uint64_t kevq_last_nkev;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,18 +75,17 @@ struct kevq {
|
|||||||
struct kqdom {
|
struct kqdom {
|
||||||
/* static */
|
/* static */
|
||||||
int id;
|
int id;
|
||||||
struct mtx kqd_lock;
|
struct rwlock kqd_lock;
|
||||||
struct kqdom *parent;
|
struct kqdom *parent;
|
||||||
cpuset_t cpu_mask;
|
cpuset_t cpu_mask;
|
||||||
struct veclist children; /* child kqdoms */
|
struct veclist children; /* child kqdoms */
|
||||||
|
|
||||||
/* statistics. Atomically updated, doesn't require the lock*/
|
/* statistics. Atomically updated, doesn't require the lock*/
|
||||||
unsigned long avg_lat;
|
uint64_t avg_lat;
|
||||||
|
|
||||||
/* dynamic members*/
|
/* dynamic members*/
|
||||||
struct veclist kqd_activelist; /* active child kqdoms */
|
struct veclist kqd_activelist; /* active child kqdoms */
|
||||||
struct veclist kqd_kevqs; /* kevqs for this kqdom */
|
struct veclist kqd_kevqs; /* kevqs for this kqdom */
|
||||||
int kqd_ckevq; /* current kevq for round robbin. XXX: Remove round robbin it has literally no benefit but maintainance nightmares */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kqueue {
|
struct kqueue {
|
||||||
@ -113,13 +112,16 @@ struct kqueue {
|
|||||||
struct ucred *kq_cred;
|
struct ucred *kq_cred;
|
||||||
struct kevqlist kq_kevqlist; /* list of kevqs */
|
struct kevqlist kq_kevqlist; /* list of kevqs */
|
||||||
|
|
||||||
/* scheduling stuff */
|
/* scheduler flags for the KQ, set by IOCTL */
|
||||||
int kq_sched_flags; /* Scheduler flag for the KQ */
|
int kq_sflags;
|
||||||
/* Round robbin (only as a fall back) */
|
int kq_ssargs;
|
||||||
struct kevq *kq_ckevq; /* current kevq for multithreaded kqueue, used for round robbin */
|
int kq_ssched;
|
||||||
/* Best of two */
|
int kq_sfargs;
|
||||||
struct rwlock sched_bot_lk;
|
|
||||||
struct veclist sched_bot_lst;
|
/* Default */
|
||||||
|
struct rwlock kevq_vlist_lk;
|
||||||
|
struct veclist kevq_vlist;
|
||||||
|
|
||||||
/* CPU queue */
|
/* CPU queue */
|
||||||
struct kqdom *kq_kqd; /* root domain */
|
struct kqdom *kq_kqd; /* root domain */
|
||||||
};
|
};
|
||||||
|
@ -51,26 +51,6 @@ struct thread_info g_thrd_info[THREAD_CNT];
|
|||||||
/* Test threads signals this upon receiving events */
|
/* Test threads signals this upon receiving events */
|
||||||
sem_t g_sem_driver;
|
sem_t g_sem_driver;
|
||||||
|
|
||||||
static void
|
|
||||||
check_sched(struct thread_info *info, int size, unsigned int max_diff)
|
|
||||||
{
|
|
||||||
int max = 0, min = INT_MAX;
|
|
||||||
|
|
||||||
for(int i = 0; i < size; i++) {
|
|
||||||
int cur = info[i].evcnt;
|
|
||||||
if (cur > max) {
|
|
||||||
max = cur;
|
|
||||||
}
|
|
||||||
if (cur < min) {
|
|
||||||
min = cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((max - min) > max_diff) {
|
|
||||||
err(1, "READ_M: check_sched: max difference is %d\n", max - min);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char
|
static char
|
||||||
socket_pop(int sockfd)
|
socket_pop(int sockfd)
|
||||||
{
|
{
|
||||||
@ -189,12 +169,8 @@ test_socket_read(int delay)
|
|||||||
socket_push(g_sockfd[1], '.');
|
socket_push(g_sockfd[1], '.');
|
||||||
/* wait for thread events */
|
/* wait for thread events */
|
||||||
sem_wait(&g_sem_driver);
|
sem_wait(&g_sem_driver);
|
||||||
|
|
||||||
if (!delay)
|
|
||||||
check_sched(g_thrd_info, THREAD_CNT, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST_DEBUG
|
#ifdef TEST_DEBUG
|
||||||
printf("READ_M: finished testing, system shutting down...\n");
|
printf("READ_M: finished testing, system shutting down...\n");
|
||||||
#endif
|
#endif
|
||||||
@ -386,6 +362,11 @@ test_socket_queue(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dump KQ */
|
||||||
|
error = ioctl(g_kqfd, FKQMPRNT);
|
||||||
|
if (error == -1) {
|
||||||
|
err(1, "dump ioctl failed");
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST_DEBUG
|
#ifdef TEST_DEBUG
|
||||||
printf("READ_M: finished testing, system shutting down...\n");
|
printf("READ_M: finished testing, system shutting down...\n");
|
||||||
@ -717,63 +698,76 @@ test_evfilt_read_m()
|
|||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
g_kqfd = kqueue();
|
g_kqfd = kqueue();
|
||||||
|
|
||||||
|
/* Default rand */
|
||||||
int error = ioctl(g_kqfd, FKQMULTI, &flags);
|
int error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
if (error == -1) {
|
if (error == -1) {
|
||||||
err(1, "ioctl");
|
err(1, "ioctl");
|
||||||
}
|
}
|
||||||
|
|
||||||
test_socket_read(0);
|
test_socket_read(0);
|
||||||
test_socket_brutal("round robbin");
|
test_socket_brutal("rand");
|
||||||
|
|
||||||
close(g_kqfd);
|
close(g_kqfd);
|
||||||
|
|
||||||
/* test scheduler */
|
/* Queue + bo0 */
|
||||||
flags = KQ_SCHED_QUEUE;
|
flags = KQSCHED_MAKE(KQ_SCHED_QUEUE,0,0,0);
|
||||||
g_kqfd = kqueue();
|
g_kqfd = kqueue();
|
||||||
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
if (error == -1) {
|
if (error == -1) {
|
||||||
err(1, "ioctl");
|
err(1, "ioctl");
|
||||||
}
|
}
|
||||||
|
test_socket_queue();
|
||||||
//test_socket_queue();
|
test_socket_brutal("queue0");
|
||||||
test_socket_brutal("queue");
|
|
||||||
|
|
||||||
close(g_kqfd);
|
close(g_kqfd);
|
||||||
|
|
||||||
|
/* CPU + Bo0 */
|
||||||
flags = KQ_SCHED_CPU;
|
flags = KQSCHED_MAKE(KQ_SCHED_CPU,0,0,0);;
|
||||||
g_kqfd = kqueue();
|
g_kqfd = kqueue();
|
||||||
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
if (error == -1) {
|
if (error == -1) {
|
||||||
err(1, "ioctl");
|
err(1, "ioctl");
|
||||||
}
|
}
|
||||||
|
test_socket_brutal("cpu0");
|
||||||
test_socket_brutal("cpu");
|
|
||||||
|
|
||||||
close(g_kqfd);
|
close(g_kqfd);
|
||||||
|
|
||||||
|
/* CPU + Bo1 */
|
||||||
flags = KQ_SCHED_WS;
|
flags = KQSCHED_MAKE(KQ_SCHED_CPU,1,0,0);;
|
||||||
g_kqfd = kqueue();
|
g_kqfd = kqueue();
|
||||||
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
if (error == -1) {
|
if (error == -1) {
|
||||||
err(1, "ioctl");
|
err(1, "ioctl");
|
||||||
}
|
}
|
||||||
|
test_socket_brutal("cpu1");
|
||||||
test_socket_ws();
|
|
||||||
test_socket_brutal("work stealing");
|
|
||||||
close(g_kqfd);
|
close(g_kqfd);
|
||||||
|
|
||||||
flags = KQ_SCHED_BOT;
|
/* CPU + Bo2 */
|
||||||
|
flags = KQSCHED_MAKE(KQ_SCHED_CPU,2,0,0);
|
||||||
g_kqfd = kqueue();
|
g_kqfd = kqueue();
|
||||||
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
if (error == -1) {
|
if (error == -1) {
|
||||||
err(1, "ioctl");
|
err(1, "ioctl");
|
||||||
}
|
}
|
||||||
|
test_socket_brutal("cpu2");
|
||||||
|
close(g_kqfd);
|
||||||
|
|
||||||
test_socket_brutal("best of two");
|
/* BO2 */
|
||||||
|
flags = KQSCHED_MAKE(KQ_SCHED_BEST,2,0,0);
|
||||||
|
g_kqfd = kqueue();
|
||||||
|
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
|
if (error == -1) {
|
||||||
|
err(1, "ioctl");
|
||||||
|
}
|
||||||
|
test_socket_brutal("best2");
|
||||||
test_socket_read(1);
|
test_socket_read(1);
|
||||||
|
close(g_kqfd);
|
||||||
|
|
||||||
|
/* WS */
|
||||||
|
flags = KQSCHED_MAKE(0,0,KQ_SCHED_FLAG_WS,1);;
|
||||||
|
g_kqfd = kqueue();
|
||||||
|
error = ioctl(g_kqfd, FKQMULTI, &flags);
|
||||||
|
if (error == -1) {
|
||||||
|
err(1, "ioctl");
|
||||||
|
}
|
||||||
|
test_socket_ws();
|
||||||
|
test_socket_brutal("ws1");
|
||||||
close(g_kqfd);
|
close(g_kqfd);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user