/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT 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. ChibiOS/RT 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 this program. If not, see . */ /** * @file chschd.c * @brief Scheduler code. * * @addtogroup scheduler * @details This module provides the default portable scheduler code, * scheduler functions can be individually captured by the port * layer in order to provide architecture optimized equivalents. * When a function is captured its default code is not built into * the OS image, the optimized version is included instead. * @{ */ #include "ch.h" /** * @brief Ready list header. */ #if !defined(PORT_OPTIMIZED_RLIST_VAR) || defined(__DOXYGEN__) ReadyList rlist; #endif /* !defined(PORT_OPTIMIZED_RLIST_VAR) */ /** * @brief Scheduler initialization. * * @notapi */ void _scheduler_init(void) { queue_init(&rlist.r_queue); rlist.r_prio = NOPRIO; #if CH_USE_REGISTRY rlist.r_newer = rlist.r_older = (Thread *)&rlist; #endif } /** * @brief Inserts a thread in the Ready List. * @details The thread is positioned behind all threads with higher or equal * priority. * @pre The thread must not be already inserted in any list through its * @p p_next and @p p_prev or list corruption would occur. * @post This function does not reschedule so a call to a rescheduling * function must be performed before unlocking the kernel. Note that * interrupt handlers always reschedule on exit so an explicit * reschedule must not be performed in ISRs. * * @param[in] tp the thread to be made ready * @return The thread pointer. * * @iclass */ #if !defined(PORT_OPTIMIZED_READYI) || defined(__DOXYGEN__) Thread *chSchReadyI(Thread *tp) { Thread *cp; chDbgCheckClassI(); /* Integrity checks.*/ chDbgAssert((tp->p_state != THD_STATE_READY) && (tp->p_state != THD_STATE_FINAL), "chSchReadyI(), #1", "invalid state"); tp->p_state = THD_STATE_READY; cp = (Thread *)&rlist.r_queue; do { cp = cp->p_next; } while (cp->p_prio >= tp->p_prio); /* Insertion on p_prev.*/ tp->p_next = cp; tp->p_prev = cp->p_prev; tp->p_prev->p_next = cp->p_prev = tp; return tp; } #endif /* !defined(PORT_OPTIMIZED_READYI) */ /** * @brief Puts the current thread to sleep into the specified state. * @details The thread goes into a sleeping state. The possible * @ref thread_states are defined into @p threads.h. * * @param[in] newstate the new thread state * * @sclass */ #if !defined(PORT_OPTIMIZED_GOSLEEPS) || defined(__DOXYGEN__) void chSchGoSleepS(tstate_t newstate) { Thread *otp; chDbgCheckClassS(); (otp = currp)->p_state = newstate; #if CH_TIME_QUANTUM > 0 /* The thread is renouncing its remaining time slices so it will have a new time quantum when it will wakeup.*/ otp->p_preempt = CH_TIME_QUANTUM; #endif setcurrp(fifo_remove(&rlist.r_queue)); currp->p_state = THD_STATE_CURRENT; chSysSwitch(currp, otp); } #endif /* !defined(PORT_OPTIMIZED_GOSLEEPS) */ #if !defined(PORT_OPTIMIZED_GOSLEEPTIMEOUTS) || defined(__DOXYGEN__) /* * Timeout wakeup callback. */ static void wakeup(void *p) { Thread *tp = (Thread *)p; chSysLockFromIsr(); switch (tp->p_state) { case THD_STATE_READY: /* Handling the special case where the thread has been made ready by another thread with higher priority.*/ chSysUnlockFromIsr(); return; #if CH_USE_SEMAPHORES || CH_USE_QUEUES || \ (CH_USE_CONDVARS && CH_USE_CONDVARS_TIMEOUT) #if CH_USE_SEMAPHORES case THD_STATE_WTSEM: chSemFastSignalI((Semaphore *)tp->p_u.wtobjp); /* Falls into, intentional. */ #endif #if CH_USE_QUEUES case THD_STATE_WTQUEUE: #endif #if CH_USE_CONDVARS && CH_USE_CONDVARS_TIMEOUT case THD_STATE_WTCOND: #endif /* States requiring dequeuing.*/ dequeue(tp); #endif } tp->p_u.rdymsg = RDY_TIMEOUT; chSchReadyI(tp); chSysUnlockFromIsr(); } /** * @brief Puts the current thread to sleep into the specified state with * timeout specification. * @details The thread goes into a sleeping state, if it is not awakened * explicitly within the specified timeout then it is forcibly * awakened with a @p RDY_TIMEOUT low level message. The possible * @ref thread_states are defined into @p threads.h. * * @param[in] newstate the new thread state * @param[in] time the number of ticks before the operation timeouts, the * special values are handled as follow: * - @a TIME_INFINITE the thread enters an infinite sleep * state, this is equivalent to invoking * @p chSchGoSleepS() but, of course, less efficient. * - @a TIME_IMMEDIATE this value is not allowed. * . * @return The wakeup message. * @retval RDY_TIMEOUT if a timeout occurs. * * @sclass */ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) { chDbgCheckClassS(); if (TIME_INFINITE != time) { VirtualTimer vt; chVTSetI(&vt, time, wakeup, currp); chSchGoSleepS(newstate); if (chVTIsArmedI(&vt)) chVTResetI(&vt); } else chSchGoSleepS(newstate); return currp->p_u.rdymsg; } #endif /* !defined(PORT_OPTIMIZED_GOSLEEPTIMEOUTS) */ /** * @brief Wakes up a thread. * @details The thread is inserted into the ready list or immediately made * running depending on its relative priority compared to the current * thread. * @pre The thread must not be already inserted in any list through its * @p p_next and @p p_prev or list corruption would occur. * @note It is equivalent to a @p chSchReadyI() followed by a * @p chSchRescheduleS() but much more efficient. * @note The function assumes that the current thread has the highest * priority. * * @param[in] ntp the Thread to be made ready * @param[in] msg message to the awakened thread * * @sclass */ #if !defined(PORT_OPTIMIZED_WAKEUPS) || defined(__DOXYGEN__) void chSchWakeupS(Thread *ntp, msg_t msg) { chDbgCheckClassS(); ntp->p_u.rdymsg = msg; /* If the waken thread has a not-greater priority than the current one then it is just inserted in the ready list else it made running immediately and the invoking thread goes in the ready list instead.*/ if (ntp->p_prio <= currp->p_prio) chSchReadyI(ntp); else { Thread *otp = chSchReadyI(currp); setcurrp(ntp); ntp->p_state = THD_STATE_CURRENT; chSysSwitch(ntp, otp); } } #endif /* !defined(PORT_OPTIMIZED_WAKEUPS) */ /*
import logging

from . import lsp
from .workspace import Workspace

log = logging.getLogger(__name__)


class VhdlLanguageServer(object):
    def __init__(self):
        self.workspace = None
        self.lsp = None
        self._shutdown = False
        self.dispatcher = {
            'initialize': self.initialize,
            'initialized': self.initialized,
            'shutdown': self.shutdown,
            '$/setTraceNotification': self.setTraceNotification,
            'textDocument/didOpen': self.textDocument_didOpen,
            'textDocument/didChange': self.textDocument_didChange,
            'textDocument/didClose': self.textDocument_didClose,
            'textDocument/didSave': self.textDocument_didSave,
            # 'textDocument/hover': self.hover,
            'textDocument/definition': self.textDocument_definition,
            'textDocument/documentSymbol': self.textDocument_documentSymbol,
            # 'textDocument/completion': self.completion,
            'textDocument/rangeFormatting': self.textDocument_rangeFormatting,
            'workspace/xShowAllFiles': self.workspace_xShowAllFiles,
            'workspace/xGetAllEntities': self.workspace_xGetAllEntities,
            'workspace/xGetEntityInterface': self.workspace_xGetEntityInterface,
            }

    def set_lsp(self, server):
        self.lsp = server

    def shutdown(self):
        self.lsp.shutdown()

    def setTraceNotification(self, value):
        pass

    def capabilities(self):
        server_capabilities = {
            'textDocumentSync': {
                'openClose': True,
                'change': lsp.TextDocumentSyncKind.INCREMENTAL,
                'save': {
                    'includeText': True}
                },
            'hoverProvider': False,
            #            'completionProvider': False,
            #            'signatureHelpProvider': {
            #                'triggerCharacters': ['(', ',']
            #            },
            'definitionProvider': True,
            'referencesProvider': False,
            'documentHighlightProvider': False,
            'documentSymbolProvider': True,
            'codeActionProvider': False,
            'documentFormattingProvider': False,
            'documentRangeFormattingProvider': True,
            'renameProvider': False,
        }
        return server_capabilities

    def initialize(self, processId, rootPath, capabilities, rootUri=None,
                   initializationOptions=None, **_):
        log.debug('Language server initialized with %s %s %s %s',
                  processId, rootUri, rootPath, initializationOptions)
        if rootUri is None:
            rootUri = lsp.path_to_uri(rootPath) if rootPath is not None else ''
        self.workspace = Workspace(rootUri, self.lsp)

        # Get our capabilities
        return {'capabilities': self.capabilities()}

    def initialized(self):
        # Event when the client is fully initialized.
        return None

    def textDocument_didOpen(self, textDocument=None):
        doc_uri = textDocument['uri']
        self.workspace.put_document(doc_uri, textDocument['text'],
                                    version=textDocument.get('version'))
        self.lint(doc_uri)

    def textDocument_didChange(self, textDocument=None, contentChanges=None,
                               **_kwargs):
        doc_uri = textDocument['uri']
        new_version = textDocument.get('version')
        self.workspace.apply_changes(doc_uri, contentChanges, new_version)

    def lint(self, doc_uri):
        self.workspace.lint(doc_uri)

    def textDocument_didClose(self, textDocument=None, **_kwargs):
        self.workspace.rm_document(textDocument['uri'])

    def textDocument_didSave(self, textDocument=None, text=None, **_kwargs):
        if text is not None:
            # Sanity check: check we have the same content for the document.
            self.workspace.check_document(textDocument['uri'], text)
        else:
            log.debug("did save - no text")
        self.lint(textDocument['uri'])

    def textDocument_definition(self, textDocument=None, position=None):
        return self.workspace.goto_definition(textDocument['uri'], position)

    def textDocument_documentSymbol(self, textDocument=None):
        doc = self.workspace.get_or_create_document(textDocument['uri'])
        return doc.document_symbols()

    def textDocument_rangeFormatting(self, textDocument=None, range=None, options=None):
        doc_uri = textDocument['uri']
        doc = self.workspace.get_document(doc_uri)
        assert doc is not None, 'Try to format a non-loaded document'
        res = doc.format_range(range)
        if res is not None:
            self.lint(doc_uri)
        return res

    def m_workspace__did_change_configuration(self, _settings=None):
        for doc_uri in self.workspace.documents:
            self.lint(doc_uri)

    def m_workspace__did_change_watched_files(self, **_kwargs):
        # Externally changed files may result in changed diagnostics
        for doc_uri in self.workspace.documents:
            self.lint(doc_uri)

    def workspace_xShowAllFiles(self):
        return self.workspace.x_show_all_files()

    def workspace_xGetAllEntities(self):
        return self.workspace.x_get_all_entities()

    def workspace_xGetEntityInterface(self, library, name):
        return self.workspace.x_get_entity_interface(library, name)