feat: taken qsort from PDCLIB, Sorting drivers. Generic driver
structure. Driver ranking
This commit is contained in:
@@ -674,13 +674,13 @@ uint8_t ide_access(uint8_t direction, uint8_t drive, uint32_t lba, uint8_t numse
|
|||||||
PCI_DRIVER(
|
PCI_DRIVER(
|
||||||
.name = "pci-ide",
|
.name = "pci-ide",
|
||||||
.description = "Default PCI IDE Driver",
|
.description = "Default PCI IDE Driver",
|
||||||
.order = 0xFF, // let other block_dev_drivers precede if they can
|
.rank = 10000, // let other block_dev_drivers precede if they can
|
||||||
.pci_use_subclass = true,
|
|
||||||
.validatable = true,
|
.validatable = true,
|
||||||
.initialisable = true,
|
.initialisable = true,
|
||||||
.pci_class = PCI_CLASS_MASS_STORAGE,
|
.match.class = PCI_CLASS_MASS_STORAGE,
|
||||||
.pci_subclass = PCI_SUB_CLASS_IDE,
|
.match.subclass = PCI_SUB_CLASS_IDE,
|
||||||
|
.mask.class = true,
|
||||||
|
.mask.subclass = true,
|
||||||
.validate = ide_pci_validate,
|
.validate = ide_pci_validate,
|
||||||
.initialize = ide_pci_initialize,
|
.initialize = ide_pci_initialize,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#ifdef ENABLE_PCIPP
|
#ifdef ENABLE_PCIPP
|
||||||
|
|
||||||
#include <drivers/pci_devices.h>
|
#include <drivers/pci_devices.h>
|
||||||
|
#include <libc/sort.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -34,17 +35,6 @@
|
|||||||
#define MASK_BAR_IOSPACE 0xFFFFFFFC
|
#define MASK_BAR_IOSPACE 0xFFFFFFFC
|
||||||
#define MASK_BAR_MEMSPACE 0xFFFFFFF0
|
#define MASK_BAR_MEMSPACE 0xFFFFFFF0
|
||||||
|
|
||||||
const struct pci_driver pci_internal_secondary_bus = {
|
|
||||||
.name = "pci-secondary-bus",
|
|
||||||
.description = "A PCI bus connected to the primary bus",
|
|
||||||
.order = 0,
|
|
||||||
.pci_class = 0x06,
|
|
||||||
.pci_subclass = 0x04,
|
|
||||||
.pci_use_subclass = true,
|
|
||||||
.validate = NULL,
|
|
||||||
.initialize = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
//const pci_driver *pci_drivers[MAX_PCI_DRIVERS];
|
//const pci_driver *pci_drivers[MAX_PCI_DRIVERS];
|
||||||
extern struct pci_driver __start_pci_driver[];
|
extern struct pci_driver __start_pci_driver[];
|
||||||
extern struct pci_driver __stop_pci_driver[];
|
extern struct pci_driver __stop_pci_driver[];
|
||||||
@@ -55,6 +45,13 @@ pci_device pci_devices[MAX_PCI_DEVICES];
|
|||||||
|
|
||||||
void pci_check_bus(uint8_t bus);
|
void pci_check_bus(uint8_t bus);
|
||||||
|
|
||||||
|
uint8_t used pci_secondary_bus_use(const pci_device *device) {
|
||||||
|
uint8_t secondary_bus = pci_config_read_byte(device->bus, device->slot, device->func,
|
||||||
|
PCI_CONFIG_SECONDARY_BUS_NUMBER);
|
||||||
|
pci_check_bus(secondary_bus);
|
||||||
|
return PCI_USE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t pci_config_address(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
|
uint32_t pci_config_address(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
|
||||||
return PCI_CONFIG_ENABLE
|
return PCI_CONFIG_ENABLE
|
||||||
| ((uint32_t) bus << PCI_CONFIG_SHIFT_BUS_NUMBER)
|
| ((uint32_t) bus << PCI_CONFIG_SHIFT_BUS_NUMBER)
|
||||||
@@ -124,32 +121,35 @@ uint8_t pci_get_header_type(uint8_t bus, uint8_t slot, uint8_t func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pci_pick_driver(pci_device *device) {
|
void pci_pick_driver(pci_device *device) {
|
||||||
// check special drivers
|
|
||||||
// PCI Secondary bus
|
|
||||||
if (device->class == pci_internal_secondary_bus.pci_class &&
|
|
||||||
device->subclass == pci_internal_secondary_bus.pci_subclass) {
|
|
||||||
uint8_t secondary_bus = pci_config_read_byte(device->bus, device->slot, device->func,
|
|
||||||
PCI_CONFIG_SECONDARY_BUS_NUMBER);
|
|
||||||
device->pci_driver = &pci_internal_secondary_bus;
|
|
||||||
pci_check_bus(secondary_bus);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use normal drivers
|
|
||||||
for (size_t i = 0; i < NUM_DRIVERS; ++i) {
|
for (size_t i = 0; i < NUM_DRIVERS; ++i) {
|
||||||
if (DRIVER(i) == NULL) {
|
struct pci_driver *driver = DRIVER(i);
|
||||||
|
if (driver == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (device->class != DRIVER(i)->pci_class) {
|
if (driver->mask.class && driver->match.class != device->class) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (DRIVER(i)->pci_use_subclass && device->subclass != DRIVER(i)->pci_subclass) {
|
if (driver->mask.subclass && driver->match.subclass != device->subclass) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!DRIVER(i)->validatable) {
|
if (driver->mask.interface && driver->match.interface != device->programInterface) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (DRIVER(i)->validate(device) != PCI_VALIDATE_OK) {
|
if (driver->mask.vendor && driver->match.vendor != device->vendorId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (driver->mask.device && driver->match.device != device->deviceId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (driver->direct_use) {
|
||||||
|
if (driver->use(device) != PCI_USE_OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (driver->validatable) {
|
||||||
|
if (driver->validate(device) != PCI_VALIDATE_OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
device->pci_driver = DRIVER(i);
|
device->pci_driver = DRIVER(i);
|
||||||
@@ -192,8 +192,19 @@ void pci_check_bus(uint8_t bus) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pci_driver_compare(const void* a, const void* b) {
|
||||||
|
int rank_a = ((struct pci_driver *) a)->rank;
|
||||||
|
int rank_b = ((struct pci_driver *) b)->rank;
|
||||||
|
if (rank_a > rank_b) {
|
||||||
|
return 1;
|
||||||
|
} else if (rank_a < rank_b) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void pci_sort_drivers() {
|
void pci_sort_drivers() {
|
||||||
// todo
|
qsort(DRIVER(0), NUM_DRIVERS, sizeof(struct pci_driver), pci_driver_compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_scan() {
|
void pci_scan() {
|
||||||
@@ -373,4 +384,17 @@ void pci_init_bar(pci_device *device, uint8_t bar_index) {
|
|||||||
bar->present = 1;
|
bar->present = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// internal drivers
|
||||||
|
PCI_DRIVER(
|
||||||
|
.name = "pci-secondary-bus",
|
||||||
|
.description = "A PCI bus connected to the primary bus",
|
||||||
|
.rank = 0, // internal driver for PCI bus
|
||||||
|
.match.class = PCI_CLASS_BRIDGE,
|
||||||
|
.match.subclass = PCI_SUB_CLASS_PCI_PCI_BRIDGE_4,
|
||||||
|
.mask.class = true,
|
||||||
|
.mask.subclass = true,
|
||||||
|
.direct_use = true,
|
||||||
|
.use = pci_secondary_bus_use,
|
||||||
|
);
|
||||||
|
|
||||||
// todo https://wiki.osdev.org/Universal_Serial_Bus if i dare
|
// todo https://wiki.osdev.org/Universal_Serial_Bus if i dare
|
||||||
@@ -10,10 +10,15 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
|
|
||||||
#define PCI_CLASS_MASS_STORAGE 0x01
|
#define PCI_CLASS_MASS_STORAGE 0x01
|
||||||
|
#define PCI_CLASS_BRIDGE 0x06
|
||||||
|
|
||||||
// class MASS STORAGE 1
|
// class MASS STORAGE 0x01
|
||||||
#define PCI_SUB_CLASS_IDE 0x01
|
#define PCI_SUB_CLASS_IDE 0x01
|
||||||
|
|
||||||
|
// class BRIDGE 0x06
|
||||||
|
#define PCI_SUB_CLASS_PCI_PCI_BRIDGE_4 0x04
|
||||||
|
#define PCI_SUB_CLASS_PCI_PCI_BRIDGE_9 0x09
|
||||||
|
|
||||||
#define PCI_REGISTER_OK 0
|
#define PCI_REGISTER_OK 0
|
||||||
#define PCI_REGISTER_ERR_FULL (-1)
|
#define PCI_REGISTER_ERR_FULL (-1)
|
||||||
@@ -24,6 +29,9 @@
|
|||||||
#define PCI_INIT_OK 0
|
#define PCI_INIT_OK 0
|
||||||
#define PCI_INIT_FAIL 1
|
#define PCI_INIT_FAIL 1
|
||||||
|
|
||||||
|
#define PCI_USE_OK 0
|
||||||
|
#define PCI_USE_FAIL 1
|
||||||
|
|
||||||
#define PCI_HEADER_TYPE_MULTI_FUNC 0x80
|
#define PCI_HEADER_TYPE_MULTI_FUNC 0x80
|
||||||
#define PCI_HEADER_TYPE_ENDPOINT 0x00
|
#define PCI_HEADER_TYPE_ENDPOINT 0x00
|
||||||
#define PCI_HEADER_TYPE_PCI_PCI_BRIDGE 0x01
|
#define PCI_HEADER_TYPE_PCI_PCI_BRIDGE 0x01
|
||||||
@@ -79,6 +87,8 @@
|
|||||||
|
|
||||||
typedef struct pci_device pci_device;
|
typedef struct pci_device pci_device;
|
||||||
|
|
||||||
|
typedef uint8_t (*pci_driver_use)(const pci_device *);
|
||||||
|
|
||||||
typedef uint8_t (*pci_driver_validate)(const pci_device *);
|
typedef uint8_t (*pci_driver_validate)(const pci_device *);
|
||||||
|
|
||||||
typedef uint8_t (*pci_driver_initialize)(pci_device *);
|
typedef uint8_t (*pci_driver_initialize)(pci_device *);
|
||||||
@@ -86,14 +96,27 @@ typedef uint8_t (*pci_driver_initialize)(pci_device *);
|
|||||||
struct pci_driver {
|
struct pci_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *description;
|
const char *description;
|
||||||
uint8_t order;
|
uint16_t rank;
|
||||||
uint8_t pci_class;
|
|
||||||
uint8_t pci_subclass;
|
|
||||||
struct {
|
struct {
|
||||||
bool pci_use_subclass: 1;
|
uint8_t class;
|
||||||
|
uint8_t subclass;
|
||||||
|
uint8_t interface;
|
||||||
|
uint16_t vendor;
|
||||||
|
uint16_t device;
|
||||||
|
} match;
|
||||||
|
struct {
|
||||||
|
bool class: 1;
|
||||||
|
bool subclass: 1;
|
||||||
|
bool interface: 1;
|
||||||
|
bool vendor: 1;
|
||||||
|
bool device: 1;
|
||||||
|
} mask;
|
||||||
|
struct {
|
||||||
|
bool direct_use: 1;
|
||||||
bool validatable: 1;
|
bool validatable: 1;
|
||||||
bool initialisable: 1;
|
bool initialisable: 1;
|
||||||
};
|
};
|
||||||
|
pci_driver_use use;
|
||||||
pci_driver_validate validate;
|
pci_driver_validate validate;
|
||||||
pci_driver_initialize initialize;
|
pci_driver_initialize initialize;
|
||||||
} __attribute__((__aligned__(STRUCT_ALIGNMENT)));
|
} __attribute__((__aligned__(STRUCT_ALIGNMENT)));
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <tasks/task.h>
|
#include <tasks/task.h>
|
||||||
#include <tasks/locking.h>
|
#include <tasks/locking.h>
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
|
#include <libc/sort.h>
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
|
|
||||||
#define MAX_BLOCK_DEVS 64
|
#define MAX_BLOCK_DEVS 64
|
||||||
@@ -79,6 +80,21 @@ void block_dev_scan() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int block_dev_driver_comp(const void *a, const void *b) {
|
||||||
|
int rank_a = ((struct block_dev_driver *) a)->rank;
|
||||||
|
int rank_b = ((struct block_dev_driver *) b)->rank;
|
||||||
|
if (rank_a > rank_b) {
|
||||||
|
return 1;
|
||||||
|
} else if (rank_a < rank_b) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void block_dev_pre_init() {
|
||||||
|
qsort(DRIVER(0), NUM_DRIVERS, sizeof(struct block_dev_driver), block_dev_driver_comp);
|
||||||
|
}
|
||||||
|
|
||||||
void noreturn block_dev_task(void *data) {
|
void noreturn block_dev_task(void *data) {
|
||||||
while (true) {
|
while (true) {
|
||||||
semaphore_wait(block_semaphore);
|
semaphore_wait(block_semaphore);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ typedef uint8_t (*block_device_access)(const block_device *device, uint8_t direc
|
|||||||
|
|
||||||
struct block_dev_driver {
|
struct block_dev_driver {
|
||||||
char name[16];
|
char name[16];
|
||||||
|
uint16_t rank;
|
||||||
struct {
|
struct {
|
||||||
uint8_t root_only: 1;
|
uint8_t root_only: 1;
|
||||||
} flags;
|
} flags;
|
||||||
@@ -64,6 +65,8 @@ uint8_t block_dev_register(block_device *device);
|
|||||||
|
|
||||||
void block_dev_free(block_device *device);
|
void block_dev_free(block_device *device);
|
||||||
|
|
||||||
|
void block_dev_pre_init();
|
||||||
|
|
||||||
void block_dev_start_task();
|
void block_dev_start_task();
|
||||||
|
|
||||||
void block_dev_print_info();
|
void block_dev_print_info();
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ get_fat_table_value(uint8_t fat_type, const uint8_t *fat_table, uint32_t active_
|
|||||||
|
|
||||||
BLOCK_DEV_DRIVER(
|
BLOCK_DEV_DRIVER(
|
||||||
.name = "fat",
|
.name = "fat",
|
||||||
|
.rank = 10000,
|
||||||
.check_device = fat_check_device,
|
.check_device = fat_check_device,
|
||||||
.free_device = NULL, // todo
|
.free_device = NULL, // todo
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ void mbr_read_from_ide(uint8_t ide_drive) {
|
|||||||
|
|
||||||
BLOCK_DEV_DRIVER(
|
BLOCK_DEV_DRIVER(
|
||||||
.name = "mbr",
|
.name = "mbr",
|
||||||
|
.rank = 100,
|
||||||
.flags.root_only = 1,
|
.flags.root_only = 1,
|
||||||
.check_device = mbr_check_device,
|
.check_device = mbr_check_device,
|
||||||
.free_device = NULL, // todo
|
.free_device = NULL, // todo
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ void noreturn used kmain(multiboot_info_t *multiboot_info, uint32_t mb_name) {
|
|||||||
// identify cpu
|
// identify cpu
|
||||||
cpuidx_print_info();
|
cpuidx_print_info();
|
||||||
|
|
||||||
|
// pre init drivers
|
||||||
|
block_dev_pre_init();
|
||||||
|
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
__asm__ __volatile__("sti");
|
__asm__ __volatile__("sti");
|
||||||
// start the timer
|
// start the timer
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ int abs(int val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// next stolen form https://www.techiedelight.com/implement-itoa-function-in-c/
|
// next stolen form https://www.techiedelight.com/implement-itoa-function-in-c/
|
||||||
// inline function to swap two numbers
|
// inline function to swapc two numbers
|
||||||
void swap(char *x, char *y) {
|
void swapc(char *x, char *y) {
|
||||||
char t = *x;
|
char t = *x;
|
||||||
*x = *y;
|
*x = *y;
|
||||||
*y = t;
|
*y = t;
|
||||||
@@ -40,7 +40,7 @@ void swap(char *x, char *y) {
|
|||||||
// function to reverse buffer[i..j]
|
// function to reverse buffer[i..j]
|
||||||
char *reverse(char *buffer, int i, int j) {
|
char *reverse(char *buffer, int i, int j) {
|
||||||
while (i < j)
|
while (i < j)
|
||||||
swap(&buffer[i++], &buffer[j--]);
|
swapc(&buffer[i++], &buffer[j--]);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
129
kernel/libc/sort.c
Normal file
129
kernel/libc/sort.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 06-03-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "sort.h"
|
||||||
|
#include "libc.h"
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
// taken from https://github.com/DevSolar/pdclib/blob/master/functions/stdlib/qsort.c
|
||||||
|
|
||||||
|
/* This implementation is taken from Paul Edward's PDPCLIB.
|
||||||
|
Original code is credited to Raymond Gardner, Englewood CO.
|
||||||
|
Minor mods are credited to Paul Edwards.
|
||||||
|
Some reformatting and simplification done by Martin Baute.
|
||||||
|
All code is still Public Domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void memswp(uint8_t *i, uint8_t *j, size_t size) {
|
||||||
|
uint8_t tmp[size];
|
||||||
|
memcpy(tmp, j, size);
|
||||||
|
memcpy(j, i, size);
|
||||||
|
memcpy(i, tmp, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For small sets, insertion sort is faster than quicksort.
|
||||||
|
T is the threshold below which insertion sort will be used.
|
||||||
|
Must be 3 or larger.
|
||||||
|
*/
|
||||||
|
#define T 7
|
||||||
|
|
||||||
|
/* Macros for handling the QSort stack */
|
||||||
|
#define PREPARE_STACK void * stack[STACKSIZE]; void ** stackptr = stack
|
||||||
|
#define PUSH(base, limit) stackptr[0] = base; stackptr[1] = limit; stackptr += 2
|
||||||
|
#define POP(base, limit) stackptr -= 2; (base) = stackptr[0]; (limit) = stackptr[1]
|
||||||
|
/* TODO: Stack usage is log2( nmemb ) (minus what T shaves off the worst case).
|
||||||
|
Worst-case nmemb is platform dependent and should probably be
|
||||||
|
configured through _PDCLIB_config.h.
|
||||||
|
*/
|
||||||
|
#define STACKSIZE 64
|
||||||
|
|
||||||
|
void qsort(void *base, size_t nmemb, size_t size, int ( *compar )(const void *, const void *)) {
|
||||||
|
void *i;
|
||||||
|
void *j;
|
||||||
|
size_t thresh = T * size;
|
||||||
|
void *base_ = base;
|
||||||
|
void *limit = base_ + nmemb * size;
|
||||||
|
PREPARE_STACK;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((size_t) (limit - base_) > thresh) /* QSort for more than T elements. */
|
||||||
|
{
|
||||||
|
/* We work from second to last - first will be pivot element. */
|
||||||
|
i = base_ + size;
|
||||||
|
j = limit - size;
|
||||||
|
/* We swap first with middle element, then sort that with second
|
||||||
|
and last element so that eventually first element is the median
|
||||||
|
of the three - avoiding pathological pivots.
|
||||||
|
TODO: Instead of middle element, chose one randomly.
|
||||||
|
*/
|
||||||
|
memswp(((((size_t) (limit - base_)) / size) / 2) * size + base_, base_, size);
|
||||||
|
|
||||||
|
if (compar(i, j) > 0) {
|
||||||
|
memswp(i, j, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compar(base_, j) > 0) {
|
||||||
|
memswp(base_, j, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compar(i, base_) > 0) {
|
||||||
|
memswp(i, base_, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we have the median for pivot element, entering main Quicksort. */
|
||||||
|
for (;;) {
|
||||||
|
do {
|
||||||
|
/* move i right until *i >= pivot */
|
||||||
|
i += size;
|
||||||
|
} while (compar(i, base_) < 0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* move j left until *j <= pivot */
|
||||||
|
j -= size;
|
||||||
|
} while (compar(j, base_) > 0);
|
||||||
|
|
||||||
|
if (i > j) {
|
||||||
|
/* break loop if pointers crossed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* else swap elements, keep scanning */
|
||||||
|
memswp(i, j, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move pivot into correct place */
|
||||||
|
memswp(base_, j, size);
|
||||||
|
|
||||||
|
/* larger subfile base / limit to stack, sort smaller */
|
||||||
|
if (j - base_ > limit - i) {
|
||||||
|
/* left is larger */
|
||||||
|
PUSH(base_, j);
|
||||||
|
base_ = i;
|
||||||
|
} else {
|
||||||
|
/* right is larger */
|
||||||
|
PUSH(i, limit);
|
||||||
|
limit = j;
|
||||||
|
}
|
||||||
|
} else /* insertion sort for less than T elements */
|
||||||
|
{
|
||||||
|
for (j = base_, i = j + size; i < limit; j = i, i += size) {
|
||||||
|
for (; compar(j, j + size) > 0; j -= size) {
|
||||||
|
memswp(j, j + size, size);
|
||||||
|
|
||||||
|
if (j == base_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackptr != stack) /* if any entries on stack */
|
||||||
|
{
|
||||||
|
POP(base_, limit);
|
||||||
|
} else /* else stack empty, done */
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
kernel/libc/sort.h
Normal file
11
kernel/libc/sort.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 06-03-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_SORT_H
|
||||||
|
#define NEW_KERNEL_SORT_H
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *));
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_SORT_H
|
||||||
Reference in New Issue
Block a user