Compare commits
6 Commits
da3b30cd94
...
1d9041f2aa
Author | SHA1 | Date |
---|---|---|
Bananymous | 1d9041f2aa | |
Bananymous | a578527012 | |
Bananymous | af78a2d080 | |
Bananymous | 840000d02b | |
Bananymous | 9ea4c777ad | |
Bananymous | a33b63d066 |
|
@ -19,6 +19,7 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
namespace LibELF { class LoadableELF; }
|
namespace LibELF { class LoadableELF; }
|
||||||
|
@ -77,6 +78,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
||||||
BAN::ErrorOr<long> sys_sleep(int seconds);
|
BAN::ErrorOr<long> sys_sleep(int seconds);
|
||||||
BAN::ErrorOr<long> sys_nanosleep(const timespec* rqtp, timespec* rmtp);
|
BAN::ErrorOr<long> sys_nanosleep(const timespec* rqtp, timespec* rmtp);
|
||||||
|
BAN::ErrorOr<long> sys_setitimer(int which, const itimerval* value, itimerval* ovalue);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_setpwd(const char* path);
|
BAN::ErrorOr<long> sys_setpwd(const char* path);
|
||||||
BAN::ErrorOr<long> sys_getpwd(char* buffer, size_t size);
|
BAN::ErrorOr<long> sys_getpwd(char* buffer, size_t size);
|
||||||
|
@ -207,6 +209,9 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
|
||||||
|
// ONLY CALLED BY TIMER INTERRUPT
|
||||||
|
static void update_alarm_queue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
||||||
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
|
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
|
||||||
|
@ -275,6 +280,9 @@ namespace Kernel
|
||||||
BAN::String m_working_directory;
|
BAN::String m_working_directory;
|
||||||
BAN::Vector<Thread*> m_threads;
|
BAN::Vector<Thread*> m_threads;
|
||||||
|
|
||||||
|
uint64_t m_alarm_interval_ns { 0 };
|
||||||
|
uint64_t m_alarm_wake_time_ns { 0 };
|
||||||
|
|
||||||
mutable SpinLock m_signal_lock;
|
mutable SpinLock m_signal_lock;
|
||||||
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
||||||
uint64_t m_signal_pending_mask { 0 };
|
uint64_t m_signal_pending_mask { 0 };
|
||||||
|
|
|
@ -337,6 +337,10 @@ done:
|
||||||
{
|
{
|
||||||
ASSERT(InterruptController::get().is_in_service(IRQ_TIMER));
|
ASSERT(InterruptController::get().is_in_service(IRQ_TIMER));
|
||||||
InterruptController::get().eoi(IRQ_TIMER);
|
InterruptController::get().eoi(IRQ_TIMER);
|
||||||
|
|
||||||
|
if (Processor::current_is_bsb())
|
||||||
|
Process::update_alarm_queue();
|
||||||
|
|
||||||
Processor::scheduler().timer_interrupt();
|
Processor::scheduler().timer_interrupt();
|
||||||
|
|
||||||
auto& current_thread = Thread::current();
|
auto& current_thread = Thread::current();
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static BAN::LinkedList<Process*> s_alarm_processes;
|
||||||
static BAN::Vector<Process*> s_processes;
|
static BAN::Vector<Process*> s_processes;
|
||||||
static RecursiveSpinLock s_process_lock;
|
static RecursiveSpinLock s_process_lock;
|
||||||
|
|
||||||
|
@ -640,6 +641,112 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_setitimer(int which, const itimerval* value, itimerval* ovalue)
|
||||||
|
{
|
||||||
|
switch (which)
|
||||||
|
{
|
||||||
|
case ITIMER_PROF:
|
||||||
|
case ITIMER_REAL:
|
||||||
|
case ITIMER_VIRTUAL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
TRY(validate_pointer_access(value, sizeof(itimerval)));
|
||||||
|
if (ovalue)
|
||||||
|
TRY(validate_pointer_access(ovalue, sizeof(itimerval)));
|
||||||
|
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_process_lock);
|
||||||
|
|
||||||
|
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||||
|
|
||||||
|
if (m_alarm_wake_time_ns)
|
||||||
|
{
|
||||||
|
for (auto it = s_alarm_processes.begin(); it != s_alarm_processes.end(); it++)
|
||||||
|
{
|
||||||
|
if (*it != this)
|
||||||
|
continue;
|
||||||
|
s_alarm_processes.remove(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_alarm_wake_time_ns && ovalue)
|
||||||
|
{
|
||||||
|
const uint64_t interval_us = m_alarm_interval_ns / 1000;
|
||||||
|
ovalue->it_interval = {
|
||||||
|
.tv_sec = static_cast<time_t>(interval_us / 1'000'000),
|
||||||
|
.tv_usec = static_cast<suseconds_t>(interval_us % 1'000'000),
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint64_t remaining_us = current_ns < m_alarm_wake_time_ns ? (current_ns - m_alarm_wake_time_ns) / 1000 : 1;
|
||||||
|
ovalue->it_value = {
|
||||||
|
.tv_sec = static_cast<time_t>(remaining_us / 1'000'000),
|
||||||
|
.tv_usec = static_cast<suseconds_t>(remaining_us % 1'000'000),
|
||||||
|
};
|
||||||
|
|
||||||
|
m_alarm_interval_ns = 0;
|
||||||
|
m_alarm_wake_time_ns = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
const uint64_t value_us = value->it_value.tv_sec * 1'000'000 + value->it_value.tv_usec;
|
||||||
|
const uint64_t interval_us = value->it_interval.tv_sec * 1'000'000 + value->it_interval.tv_usec;
|
||||||
|
if (value_us)
|
||||||
|
{
|
||||||
|
const uint64_t wake_time_ns = current_ns + value_us * 1000;
|
||||||
|
|
||||||
|
auto it = s_alarm_processes.begin();
|
||||||
|
while (it != s_alarm_processes.end() && (*it)->m_alarm_wake_time_ns < wake_time_ns)
|
||||||
|
it++;
|
||||||
|
TRY(s_alarm_processes.insert(it, this));
|
||||||
|
|
||||||
|
m_alarm_wake_time_ns = wake_time_ns;
|
||||||
|
m_alarm_interval_ns = interval_us * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::update_alarm_queue()
|
||||||
|
{
|
||||||
|
ASSERT(Processor::current_is_bsb());
|
||||||
|
|
||||||
|
SpinLockGuard _(s_process_lock);
|
||||||
|
|
||||||
|
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||||
|
|
||||||
|
while (!s_alarm_processes.empty())
|
||||||
|
{
|
||||||
|
auto* process = s_alarm_processes.front();
|
||||||
|
if (current_ns < process->m_alarm_wake_time_ns)
|
||||||
|
break;
|
||||||
|
|
||||||
|
process->add_pending_signal(SIGALRM);
|
||||||
|
Processor::scheduler().unblock_thread(process->m_threads.front());
|
||||||
|
|
||||||
|
s_alarm_processes.remove(s_alarm_processes.begin());
|
||||||
|
|
||||||
|
if (process->m_alarm_interval_ns == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
process->m_alarm_wake_time_ns = current_ns + process->m_alarm_interval_ns;
|
||||||
|
|
||||||
|
auto it = s_alarm_processes.begin();
|
||||||
|
while (it != s_alarm_processes.end() && (*it)->m_alarm_wake_time_ns < process->m_alarm_wake_time_ns)
|
||||||
|
it++;
|
||||||
|
MUST(s_alarm_processes.insert(it, process));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::create_file_or_dir(BAN::StringView path, mode_t mode)
|
BAN::ErrorOr<void> Process::create_file_or_dir(BAN::StringView path, mode_t mode)
|
||||||
{
|
{
|
||||||
switch (mode & Inode::Mode::TYPE_MASK)
|
switch (mode & Inode::Mode::TYPE_MASK)
|
||||||
|
@ -1655,6 +1762,7 @@ namespace Kernel
|
||||||
|
|
||||||
if (pid == m_pid)
|
if (pid == m_pid)
|
||||||
{
|
{
|
||||||
|
if (signal)
|
||||||
add_pending_signal(signal);
|
add_pending_signal(signal);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,17 +127,23 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
switch (request)
|
switch (request)
|
||||||
{
|
{
|
||||||
case KD_LOADFONT:
|
case KDLOADFONT:
|
||||||
{
|
{
|
||||||
auto absolute_path = TRY(Process::current().absolute_path_of(BAN::StringView(reinterpret_cast<const char*>(argument))));
|
auto absolute_path = TRY(Process::current().absolute_path_of(BAN::StringView(reinterpret_cast<const char*>(argument))));
|
||||||
auto new_font = TRY(LibFont::Font::load(absolute_path));
|
auto new_font = TRY(LibFont::Font::load(absolute_path));
|
||||||
set_font(new_font);
|
set_font(new_font);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default:
|
case TIOCGWINSZ:
|
||||||
return BAN::Error::from_errno(EINVAL);
|
{
|
||||||
|
auto* winsize = static_cast<struct winsize*>(argument);
|
||||||
|
winsize->ws_col = width();
|
||||||
|
winsize->ws_row = height();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
void TTY::on_key_event(LibInput::KeyEvent event)
|
void TTY::on_key_event(LibInput::KeyEvent event)
|
||||||
{
|
{
|
||||||
|
@ -193,6 +199,9 @@ namespace Kernel
|
||||||
case LibInput::Key::Backspace:
|
case LibInput::Key::Backspace:
|
||||||
ansi_c_str = "\b";
|
ansi_c_str = "\b";
|
||||||
break;
|
break;
|
||||||
|
case LibInput::Key::Escape:
|
||||||
|
ansi_c_str = "\e";
|
||||||
|
break;
|
||||||
case LibInput::Key::ArrowUp:
|
case LibInput::Key::ArrowUp:
|
||||||
ansi_c_str = "\e[A";
|
ansi_c_str = "\e[A";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -242,6 +242,23 @@ namespace Kernel
|
||||||
else
|
else
|
||||||
dprintln("Unsupported ANSI CSI character K");
|
dprintln("Unsupported ANSI CSI character K");
|
||||||
return reset_ansi();
|
return reset_ansi();
|
||||||
|
case 'L': // Insert Line
|
||||||
|
if (m_ansi_state.nums[0] == -1)
|
||||||
|
m_ansi_state.nums[0] = 1;
|
||||||
|
for (uint32_t y_off = 0; y_off < (uint32_t)m_ansi_state.nums[0]; y_off++)
|
||||||
|
{
|
||||||
|
const uint32_t src_y = m_row + y_off;
|
||||||
|
const uint32_t dst_y = src_y + m_ansi_state.nums[0];
|
||||||
|
if (dst_y < m_height)
|
||||||
|
{
|
||||||
|
memcpy(&m_buffer[dst_y * m_width], &m_buffer[src_y * m_width], m_width * sizeof(Cell));
|
||||||
|
for (uint32_t x = 0; x < m_width; x++)
|
||||||
|
render_from_buffer(x, dst_y);
|
||||||
|
}
|
||||||
|
for (uint32_t x = 0; x < m_width; x++)
|
||||||
|
putchar_at(' ', x, src_y);
|
||||||
|
}
|
||||||
|
return reset_ansi();
|
||||||
case 'S': // Scroll Up
|
case 'S': // Scroll Up
|
||||||
dprintln("Unsupported ANSI CSI character S");
|
dprintln("Unsupported ANSI CSI character S");
|
||||||
return reset_ansi();
|
return reset_ansi();
|
||||||
|
|
|
@ -55,7 +55,7 @@ DIR* fdopendir(int fd)
|
||||||
|
|
||||||
DIR* opendir(const char* dirname)
|
DIR* opendir(const char* dirname)
|
||||||
{
|
{
|
||||||
int fd = open(dirname, O_RDONLY);
|
int fd = open(dirname, O_RDONLY | O_DIRECTORY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return fdopendir(fd);
|
return fdopendir(fd);
|
||||||
|
|
|
@ -101,7 +101,14 @@ struct str_list
|
||||||
#define I_SWROPT 28
|
#define I_SWROPT 28
|
||||||
#define I_UNLINK 29
|
#define I_UNLINK 29
|
||||||
|
|
||||||
#define KD_LOADFONT 30
|
#define KDLOADFONT 30
|
||||||
|
|
||||||
|
struct winsize
|
||||||
|
{
|
||||||
|
unsigned short ws_row;
|
||||||
|
unsigned short ws_col;
|
||||||
|
};
|
||||||
|
#define TIOCGWINSZ 50
|
||||||
|
|
||||||
#define FLUSHR 1
|
#define FLUSHR 1
|
||||||
#define FLUSHRW 2
|
#define FLUSHRW 2
|
||||||
|
|
|
@ -86,6 +86,7 @@ __BEGIN_DECLS
|
||||||
O(SYS_SIGACTION, sigaction) \
|
O(SYS_SIGACTION, sigaction) \
|
||||||
O(SYS_SIGPENDING, sigpending) \
|
O(SYS_SIGPENDING, sigpending) \
|
||||||
O(SYS_SIGPROCMASK, sigprocmask) \
|
O(SYS_SIGPROCMASK, sigprocmask) \
|
||||||
|
O(SYS_SETITIMER, setitimer) \
|
||||||
|
|
||||||
enum Syscall
|
enum Syscall
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp)
|
int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp)
|
||||||
{
|
{
|
||||||
|
@ -13,3 +15,8 @@ int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp)
|
||||||
tp->tv_usec = ts.tv_nsec / 1000;
|
tp->tv_usec = ts.tv_nsec / 1000;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int setitimer(int which, const struct itimerval* __restrict value, struct itimerval* __restrict ovalue)
|
||||||
|
{
|
||||||
|
return syscall(SYS_SETITIMER, which, value, ovalue);
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
char** environ;
|
char** environ;
|
||||||
|
@ -514,3 +515,14 @@ int access(const char* path, int amode)
|
||||||
{
|
{
|
||||||
return syscall(SYS_ACCESS, path, amode);
|
return syscall(SYS_ACCESS, path, amode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned alarm(unsigned seconds)
|
||||||
|
{
|
||||||
|
itimerval value, ovalue;
|
||||||
|
value.it_value.tv_sec = seconds;
|
||||||
|
value.it_value.tv_usec = 0;
|
||||||
|
value.it_interval.tv_sec = 0;
|
||||||
|
value.it_interval.tv_usec = 0;
|
||||||
|
setitimer(ITIMER_REAL, &value, &ovalue);
|
||||||
|
return ovalue.it_value.tv_sec;
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ int main(int argc, char** argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(STDOUT_FILENO, KD_LOADFONT, argv[1]) == -1)
|
if (ioctl(STDOUT_FILENO, KDLOADFONT, argv[1]) == -1)
|
||||||
{
|
{
|
||||||
perror("ioctl");
|
perror("ioctl");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue