diff --git a/sortix/Makefile b/sortix/Makefile index 331629d7..8e62966d 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -87,7 +87,6 @@ bga.o \ calltrace.o \ com.o \ $(CPU)/calltrace.o \ -$(CPU)/interlock.o \ $(CPU)/kthread.o \ crc32.o \ descriptors.o \ diff --git a/sortix/include/sortix/kernel/interlock.h b/sortix/include/sortix/kernel/interlock.h index a4496231..e4cdf27a 100644 --- a/sortix/include/sortix/kernel/interlock.h +++ b/sortix/include/sortix/kernel/interlock.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of Sortix. @@ -34,7 +34,7 @@ typedef struct unsigned long n; // new value } ilret_t; -// These atomicly modifies a value and return the previous value. +// These atomically modifies a value and return the previous value. ilret_t InterlockedModify(unsigned long* ptr, ilockfunc f, unsigned long user = 0); diff --git a/sortix/interlock.cpp b/sortix/interlock.cpp index e3a82242..f199681d 100644 --- a/sortix/interlock.cpp +++ b/sortix/interlock.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of Sortix. @@ -29,15 +29,20 @@ namespace Sortix { // TODO: This is likely not the most optimal way to perform these operations. -extern "C" ilret_t asm_interlocked_modify(unsigned long* val, - ilockfunc f, - unsigned long user); - ilret_t InterlockedModify(unsigned long* ptr, ilockfunc f, unsigned long user) { - return asm_interlocked_modify(ptr, f, user); + unsigned long old_value, new_value; + do + { + old_value = *((volatile unsigned long*) ptr); /* TODO: Need volatile? */ + new_value = f(old_value, user); + } while ( !__sync_bool_compare_and_swap(ptr, old_value, new_value) ); + ilret_t ret; + ret.o = old_value; + ret.n = new_value; + return ret; } static unsigned long AddFunction(unsigned long val, unsigned long arg) diff --git a/sortix/x64/interlock.s b/sortix/x64/interlock.s deleted file mode 100644 index d7430040..00000000 --- a/sortix/x64/interlock.s +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - - Copyright(C) Jonas 'Sortie' Termansen 2012. - - This file is part of Sortix. - - Sortix is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation, either version 3 of the License, or (at your option) any later - version. - - Sortix 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 General Public License for more - details. - - You should have received a copy of the GNU General Public License along with - Sortix. If not, see . - - x64/interlock.s - Functions that perform non-atomic operations in an atomic manner. - -*******************************************************************************/ - -.section .text - -# Atomicly runs a function on a value and returns the unmodified value. -# ilret_t -# asm_interlocked_modify(unsigned long* val, -# unsigned long (*func)(unsigned long, unsigned long), -# unsigned long user); -.global asm_interlocked_modify -.type asm_interlocked_modify, @function -asm_interlocked_modify: - pushq %rbp - movq %rsp, %rbp -asm_interlocked_modify_retry: - # Save our parameters in case we need to retry. - pushq %rdi - pushq %rsi - pushq %rdx - # Read the current value and calculate the replacement. - movq (%rdi), %rdi - movq %rdx, %rsi - callq *%rsi - movq %rax, %rdx - popq %rax - popq %rdi - popq %rsi - # Atomicly assign the replacement if the value is unchanged. - cmpxchgq %rdx, (%rdi) - # Retry if the value was modified by someone else. - jnz asm_interlocked_modify_retry - # Return the old value in %rax, new one in %rdx. - leaveq - retq diff --git a/sortix/x86/interlock.s b/sortix/x86/interlock.s deleted file mode 100644 index 12f990b5..00000000 --- a/sortix/x86/interlock.s +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - - Copyright(C) Jonas 'Sortie' Termansen 2012. - - This file is part of Sortix. - - Sortix is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation, either version 3 of the License, or (at your option) any later - version. - - Sortix 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 General Public License for more - details. - - You should have received a copy of the GNU General Public License along with - Sortix. If not, see . - - x86/interlock.s - Functions that perform non-atomic operations in an atomic manner. - -*******************************************************************************/ - -.section .text - -# Atomicly runs a function on a value and returns the unmodified value. -# ilret_t -# asm_interlocked_modify(unsigned long* val, -# unsigned long (*func)(unsigned long, unsigned long), -# unsigned long user); -.global asm_interlocked_modify -.type asm_interlocked_modify, @function -asm_interlocked_modify: - pushl %ebp - movl %esp, %ebp - pushl %ebx -asm_interlocked_modify_retry: - # Read the current value and calculate the replacement. - movl 20(%ebp), %ecx # user - movl 16(%ebp), %edx # func - movl 12(%ebp), %ebx # val - movl (%ebx), %ebx # *val - pushl %ecx - pushl %ebx - call *%edx - # Atomicly assign the replacement if the value is unchanged. - movl %eax, %edx # New value in %edx - movl %ebx, %eax # Old value in %eax - movl 8(%ebp), %ebx # val - cmpxchgl %edx, (%ebx) - # Retry if the value was modified by someone else. - jnz asm_interlocked_modify_retry - # According to the calling convention, the first parameter is secretly a - # pointer to where we store the result, the old value first, then the new. - movl 8(%ebp), %ebx - movl %eax, 0(%ebx) - movl %edx, 4(%ebx) - popl %ebx - leavel - retl $0x4